17 KiB
slug | sidebar_position | sidebar_label |
---|---|---|
/ja/sql-reference/functions/arithmetic-functions | 5 | 算術関数 |
算術関数
算術関数は、UInt8
、UInt16
、UInt32
、UInt64
、Int8
、Int16
、Int32
、Int64
、Float32
、もしくは Float64
型の2つのオペランドに対応します。
演算を実行する前に、両方のオペランドは結果の型にキャストされます。結果の型は以下のように決定されます(以下の関数のドキュメントで特に指定されていない限り):
- 両方のオペランドが32ビット以内であれば、結果の型のサイズは、より大きいオペランドに続く次に大きい型のサイズとなります(整数サイズの昇格)。例:
UInt8 + UInt16 = UInt32
またはFloat32 * Float32 = Float64
。 - オペランドのうちの1つが64ビット以上であれば、結果の型のサイズは2つのオペランドのうち大きい方のサイズと同じになります。例:
UInt32 + UInt128 = UInt128
またはFloat32 * Float64 = Float64
。 - オペランドのうち1つが符号付きの場合、結果の型も符号付きになります。そうでない場合は符号付きになります。例:
UInt32 * Int32 = Int64
。
これらのルールにより、すべての可能な結果を表現できる最小の型が結果の型となることが保証されます。これは値の範囲境界付近でオーバーフローのリスクを伴いますが、64ビットのネイティブ整数幅を使用して計算が迅速に行われることを保証します。この挙動は、最大整数型として64ビット整数(BIGINT)を提供する多くの他のデータベースとの互換性も保証します。
例:
SELECT toTypeName(0), toTypeName(0 + 0), toTypeName(0 + 0 + 0), toTypeName(0 + 0 + 0 + 0)
┌─toTypeName(0)─┬─toTypeName(plus(0, 0))─┬─toTypeName(plus(plus(0, 0), 0))─┬─toTypeName(plus(plus(plus(0, 0), 0), 0))─┐
│ UInt8 │ UInt16 │ UInt32 │ UInt64 │
└───────────────┴────────────────────────┴─────────────────────────────────┴──────────────────────────────────────────┘
オーバーフローはC++と同様に生成されます。
plus
2つの値 a
と b
の合計を計算します。
構文
plus(a, b)
整数と日付または時間付き日付を加算することも可能です。前者の操作は日付の日数を増加させ、後者の操作は時間付き日付の秒数を増加させます。
エイリアス: a + b
(演算子)
minus
2つの値 a
と b
の差を計算します。結果は常に符号付きです。
plus
と同様に、整数から日付または時間付き日付を引くことが可能です。
構文
minus(a, b)
エイリアス: a - b
(演算子)
multiply
2つの値 a
と b
の積を計算します。
構文
multiply(a, b)
エイリアス: a * b
(演算子)
divide
2つの値 a
と b
の商を計算します。結果の型は常に Float64 です。整数除算は intDiv
関数で提供されます。
ゼロで割ると inf
、-inf
、または nan
を返します。
構文
divide(a, b)
エイリアス: a / b
(演算子)
intDiv
2つの値 a
と b
の整数除算を行います。すなわち、商を次に小さい整数に切り下げます。
結果は被除数(最初のパラメータ)と同じ幅です。
ゼロで割るとき、商が被除数の範囲に収まらないとき、または最小の負の数を-1で割るときは例外が発生します。
構文
intDiv(a, b)
例
クエリ:
SELECT
intDiv(toFloat64(1), 0.001) AS res,
toTypeName(res)
┌──res─┬─toTypeName(intDiv(toFloat64(1), 0.001))─┐
│ 1000 │ Int64 │
└──────┴─────────────────────────────────────────┘
SELECT
intDiv(1, 0.001) AS res,
toTypeName(res)
Received exception from server (version 23.2.1):
Code: 153. DB::Exception: Received from localhost:9000. DB::Exception: Cannot perform integer division, because it will produce infinite or too large number: While processing intDiv(1, 0.001) AS res, toTypeName(res). (ILLEGAL_DIVISION)
intDivOrZero
intDiv
と同様ですが、ゼロで割る場合や最小の負の数を-1で割る場合はゼロを返します。
構文
intDivOrZero(a, b)
isFinite
Float32 または Float64 引数が無限でなく NaN でもない場合に1を返します。それ以外の場合、この関数は0を返します。
構文
isFinite(x)
isInfinite
Float32 または Float64 引数が無限である場合に1を返します。それ以外の場合、この関数は0を返します。NaN に対しては0が返されることに注意してください。
構文
isInfinite(x)
ifNotFinite
浮動小数点の値が有限かどうかをチェックします。
構文
ifNotFinite(x,y)
引数
返される値
x
が有限ならx
。x
が有限でなければy
。
例
クエリ:
SELECT 1/0 as infimum, ifNotFinite(infimum,42)
結果:
┌─infimum─┬─ifNotFinite(divide(1, 0), 42)─┐
│ inf │ 42 │
└─────────┴───────────────────────────────┘
同様の結果を三項演算子を使用して得ることができます: isFinite(x) ? x : y
。
isNaN
Float32 と Float64 引数が NaN の場合に1を返し、それ以外の場合には0を返します。
構文
isNaN(x)
modulo
2つの値 a
と b
を割った余りを計算します。
両方の入力が整数であれば、結果の型は整数です。入力の片方が浮動小数点数であれば、結果の型は Float64 です。
余りは C++ と同様に計算されます。負の数の場合、切り捨て除算が使用されます。
ゼロで割る場合や最小の負の数を-1で割る場合は例外が発生します。
構文
modulo(a, b)
エイリアス: a % b
(演算子)
moduloOrZero
modulo と同様ですが、除数がゼロの場合にはゼロを返します。
構文
moduloOrZero(a, b)
positiveModulo(a, b)
modulo と同様ですが、常に非負の数を返します。
この関数は modulo
より4-5倍遅くなります。
構文
positiveModulo(a, b)
エイリアス:
positive_modulo(a, b)
pmod(a, b)
例
クエリ:
SELECT positiveModulo(-1, 10)
結果:
┌─positiveModulo(-1, 10)─┐
│ 9 │
└────────────────────────┘
negate
値 a
を反転します。結果は常に符号付きです。
構文
negate(a)
エイリアス: -a
abs
a
の絶対値を計算します。a
が符号なし型の場合は何の効果もありません。a
が符号付き型である場合、符号なし数を返します。
構文
abs(a)
gcd
2つの値 a
と b
の最大公約数を返します。
ゼロで割る場合や最小の負の数を-1で割る場合は例外が発生します。
構文
gcd(a, b)
lcm(a, b)
2つの値 a
と b
の最小公倍数を返します。
ゼロで割る場合や最小の負の数を-1で割る場合は例外が発生します。
構文
lcm(a, b)
max2
2つの値 a
と b
のうち大きい方を返します。返される値の型は Float64 です。
構文
max2(a, b)
例
クエリ:
SELECT max2(-1, 2);
結果:
┌─max2(-1, 2)─┐
│ 2 │
└─────────────┘
min2
2つの値 a
と b
のうち小さい方を返します。返される値の型は Float64 です。
構文
min2(a, b)
例
クエリ:
SELECT min2(-1, 2);
結果:
┌─min2(-1, 2)─┐
│ -1 │
└─────────────┘
multiplyDecimal
2つの10進数 a
と b
を掛け算します。結果の値の型は Decimal256 です。
結果のスケールは result_scale
によって明示的に指定できます。result_scale
が指定されない場合、入力値の最大スケールが仮定されます。
この関数は通常の multiply
よりも大幅に遅いです。結果の精度に対する制御が必要ない場合や高速な計算が望ましい場合は、multiply
の使用を検討してください。
構文
multiplyDecimal(a, b[, result_scale])
引数
返される値
- 与えられたスケールでの乗算の結果。Decimal256。
例
┌─multiplyDecimal(toDecimal256(-12, 0), toDecimal32(-2.1, 1), 1)─┐
│ 25.2 │
└────────────────────────────────────────────────────────────────┘
通常の乗算に比べた違い:
SELECT toDecimal64(-12.647, 3) * toDecimal32(2.1239, 4);
SELECT toDecimal64(-12.647, 3) as a, toDecimal32(2.1239, 4) as b, multiplyDecimal(a, b);
結果:
┌─multiply(toDecimal64(-12.647, 3), toDecimal32(2.1239, 4))─┐
│ -26.8609633 │
└───────────────────────────────────────────────────────────┘
┌───────a─┬──────b─┬─multiplyDecimal(toDecimal64(-12.647, 3), toDecimal32(2.1239, 4))─┐
│ -12.647 │ 2.1239 │ -26.8609 │
└─────────┴────────┴──────────────────────────────────────────────────────────────────┘
SELECT
toDecimal64(-12.647987876, 9) AS a,
toDecimal64(123.967645643, 9) AS b,
multiplyDecimal(a, b);
SELECT
toDecimal64(-12.647987876, 9) AS a,
toDecimal64(123.967645643, 9) AS b,
a * b;
結果:
┌─────────────a─┬─────────────b─┬─multiplyDecimal(toDecimal64(-12.647987876, 9), toDecimal64(123.967645643, 9))─┐
│ -12.647987876 │ 123.967645643 │ -1567.941279108 │
└───────────────┴───────────────┴───────────────────────────────────────────────────────────────────────────────┘
Received exception from server (version 22.11.1):
Code: 407. DB::Exception: Received from localhost:9000. DB::Exception: Decimal math overflow: While processing toDecimal64(-12.647987876, 9) AS a, toDecimal64(123.967645643, 9) AS b, a * b. (DECIMAL_OVERFLOW)
divideDecimal
2つの10進数 a
と b
を除算します。結果の値の型は Decimal256 です。
結果のスケールは result_scale
によって明示的に指定できます。result_scale
が指定されない場合、入力値の最大スケールが仮定されます。
この関数は通常の divide
よりも大幅に遅いです。結果の精度に対する制御が必要ない場合や高速な計算が望ましい場合は、divide
の使用を検討してください。
構文
divideDecimal(a, b[, result_scale])
引数
返される値
- 与えられたスケールでの除算の結果。Decimal256。
例
┌─divideDecimal(toDecimal256(-12, 0), toDecimal32(2.1, 1), 10)─┐
│ -5.7142857142 │
└──────────────────────────────────────────────────────────────┘
通常の除算に比べた違い:
SELECT toDecimal64(-12, 1) / toDecimal32(2.1, 1);
SELECT toDecimal64(-12, 1) as a, toDecimal32(2.1, 1) as b, divideDecimal(a, b, 1), divideDecimal(a, b, 5);
結果:
┌─divide(toDecimal64(-12, 1), toDecimal32(2.1, 1))─┐
│ -5.7 │
└──────────────────────────────────────────────────┘
┌───a─┬───b─┬─divideDecimal(toDecimal64(-12, 1), toDecimal32(2.1, 1), 1)─┬─divideDecimal(toDecimal64(-12, 1), toDecimal32(2.1, 1), 5)─┐
│ -12 │ 2.1 │ -5.7 │ -5.71428 │
└─────┴─────┴────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘
SELECT toDecimal64(-12, 0) / toDecimal32(2.1, 1);
SELECT toDecimal64(-12, 0) as a, toDecimal32(2.1, 1) as b, divideDecimal(a, b, 1), divideDecimal(a, b, 5);
結果:
DB::Exception: Decimal result's scale is less than argument's one: While processing toDecimal64(-12, 0) / toDecimal32(2.1, 1). (ARGUMENT_OUT_OF_BOUND)
┌───a─┬───b─┬─divideDecimal(toDecimal64(-12, 0), toDecimal32(2.1, 1), 1)─┬─divideDecimal(toDecimal64(-12, 0), toDecimal32(2.1, 1), 5)─┐
│ -12 │ 2.1 │ -5.7 │ -5.71428 │
└─────┴─────┴────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘
byteSwap
整数のバイトを反転します。すなわち、そのエンディアンを変更します。
構文
byteSwap(a)
例
byteSwap(3351772109)
結果:
┌─byteSwap(3351772109)─┐
│ 3455829959 │
└──────────────────────┘
上記の例は次のようにして導き出せます:
- 10進数の整数をビッグエンディアン形式の16進数形式に変換します。例: 3351772109 -> C7 C7 FB CD (4バイト)
- バイトを反転します。例: C7 C7 FB CD -> CD FB C7 C7
- 結果をビッグエンディアンを仮定して整数に変換します。例: CD FB C7 C7 -> 3455829959
この関数の一つのユースケースはIPv4の反転です:
┌─toIPv4(byteSwap(toUInt32(toIPv4('205.251.199.199'))))─┐
│ 199.199.251.205 │
└───────────────────────────────────────────────────────┘