メインコンテンツまでスキップ
メインコンテンツまでスキップ

算術関数

算術関数は、UInt8UInt16UInt32UInt64Int8Int16Int32Int64Float32、または Float64 型の任意の2つのオペランドで機能します。

演算を実行する前に、両方のオペランドは結果の型にキャストされます。結果の型は以下のように決定されます(以下の関数のドキュメントで異なるように指定されていない限り):

  • 両方のオペランドが32ビット幅までである場合、結果の型のサイズは、2つのオペランドの大きい方の次に大きい型のサイズになります(整数サイズの昇格)。例えば、UInt8 + UInt16 = UInt32 または Float32 * Float32 = Float64
  • オペランドの1つが64ビット以上である場合、結果の型のサイズは2つのオペランドの大きい方と同じサイズになります。例えば、UInt32 + UInt128 = UInt128 または Float32 * Float64 = Float64
  • オペランドの1つが符号付きである場合、結果の型も符号付きになります。そうでない場合は符号なしになります。例えば、UInt32 * Int32 = Int64

これらのルールにより、結果の型はすべての可能な結果を表現できる最小の型が選択されます。これにより値の範囲の境界周辺でのオーバーフローのリスクが導入されますが、計算は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つの値 ab の合計を計算します。

構文

plus(a, b)

整数と日付または日時を追加することが可能です。前者の操作は日付の中の日数を増加させ、後者の操作は日時の日付の中の秒数を増加させます。

エイリアス: a + b (演算子)

minus

2つの値 ab の差を計算します。結果は常に符号付きです。

plus と同様に、整数を日付または日時から引くことも可能です。

さらに、日時間の引き算もサポートされており、2つの間の時間差を求めることができます。

構文

minus(a, b)

エイリアス: a - b (演算子)

multiply

2つの値 ab の積を計算します。

構文

multiply(a, b)

エイリアス: a * b (演算子)

divide

2つの値 ab の商を計算します。結果型は常にFloat64です。整数の割り算は intDiv 関数によって提供されます。

0での除算は inf-inf、または nan を返します。

構文

divide(a, b)

エイリアス: a / b (演算子)

divideOrNull

divide と同様ですが、除数がゼロの際にNULLを返します。

構文

divideOrNull(a, b)

intDiv

2つの値 ab の整数除算を行います。つまり、商を次の最小の整数に切り下げて計算します。

結果は被除数(最初のパラメータ)と同じ幅を持ちます。

ゼロでの除算、商が被除数の範囲に収まらない場合、または最小の負数をマイナス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)

intDivOrNull

intDiv と同様ですが、除数がゼロの場合にNULLを返します。

構文

intDivOrNull(a, b)

isFinite

Float32 または Float64 引数が無限大でなく、NaNでもない場合は1を返します。それ以外の場合はこの関数は0を返します。

構文

isFinite(x)

isInfinite

Float32 または Float64 引数が無限大である場合は1を返します。それ以外の場合はこの関数は0を返します。NaNの場合は0が返されます。

構文

isInfinite(x)

ifNotFinite

浮動小数点値が有限かどうかをチェックします。

構文

ifNotFinite(x,y)

引数

  • x — 無限大かどうかをチェックする値。 Float*
  • y — フォールバック値。 Float*

返される値

  • 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つの値 ab で割った余りを計算します。

入力が両方とも整数の場合、結果型は整数になります。1つでも浮動小数点数が存在する場合、結果型は Float64 になります。

余りはC++のように計算されます。負の数に対しては切り捨て除算が使用されます。

ゼロで割るときや最小の負数をマイナス1で割るときには例外がスローされます。

構文

modulo(a, b)

エイリアス: a % b (演算子)

moduloOrZero

modulo と同様ですが、除数がゼロの際にはゼロを返します。

構文

moduloOrZero(a, b)

moduloOrNull

modulo と同様ですが、除数がゼロの際にNULLを返します。

構文

moduloOrNull(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 │
└────────────────────────┘

positiveModuloOrNull(a, b)

positiveModulo と同様ですが、除数がゼロの場合はNULLを返します。

構文

positiveModuloOrNull(a, b)

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つの小数 ab を掛け算します。結果の値はDecimal256型になります。

結果のスケールは result_scale で明示的に指定できます。result_scale が指定されていない場合、入力値の最大スケールとみなされます。

この関数は通常の multiply よりも顕著に遅く動作します。結果の精度に対する制御が不要であり、あるいは高速な計算が望まれる場合は multiply の使用を検討してください。

構文

multiplyDecimal(a, b[, result_scale])

引数

  • a — 最初の値。Decimal
  • b — 2番目の値。Decimal
  • result_scale — 結果のスケール。Int/UInt

返される値

  • 指定されたスケールでの乗算の結果。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つの小数 ab を割ります。結果の値はDecimal256型になります。

結果のスケールは result_scale で明示的に指定できます。result_scale が指定されていない場合、入力値の最大スケールとみなされます。

この関数は通常の divide よりも顕著に遅く動作します。結果の精度に対する制御が不要であり、あるいは高速な計算が望まれる場合は divide の使用を検討してください。

構文

divideDecimal(a, b[, result_scale])

引数

  • a — 最初の値: Decimal
  • b — 2番目の値: Decimal
  • result_scale — 結果のスケール: Int/UInt

返される値

  • 指定されたスケールでの除算の結果。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 │
└──────────────────────┘

上記の例は、次のように計算されます:

  1. 10進数の整数をビッグエンディアン形式の相当な16進数フォーマットに変換します。すなわち3351772109 -> C7 C7 FB CD (4バイト)
  2. バイトを反転します。すなわちC7 C7 FB CD -> CD FB C7 C7
  3. 結果をビッグエンディアンと仮定して整数に戻します。すなわちCD FB C7 C7 -> 3455829959

この関数の使い方の一例はIPv4を反転させることです:

┌─toIPv4(byteSwap(toUInt32(toIPv4('205.251.199.199'))))─┐
│ 199.199.251.205                                       │
└───────────────────────────────────────────────────────┘