ClickHouse/docs/ja/sql-reference/functions/arithmetic-functions.md
2024-11-18 11:58:58 +09:00

17 KiB
Raw Blame History

slug sidebar_position sidebar_label
/ja/sql-reference/functions/arithmetic-functions 5 算術関数

算術関数

算術関数は、UInt8UInt16UInt32UInt64Int8Int16Int32Int64Float32、もしくは 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つの値 ab の合計を計算します。

構文

plus(a, b)

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

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

minus

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

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

構文

minus(a, b)

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

multiply

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

構文

multiply(a, b)

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

divide

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

ゼロで割ると inf-inf、または nan を返します。

構文

divide(a, b)

エイリアス: 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)

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 を割った余りを計算します。

両方の入力が整数であれば、結果の型は整数です。入力の片方が浮動小数点数であれば、結果の型は 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つの値 ab の最大公約数を返します。

ゼロで割る場合や最小の負の数を-1で割る場合は例外が発生します。

構文

gcd(a, b)

lcm(a, b)

2つの値 ab の最小公倍数を返します。

ゼロで割る場合や最小の負の数を-1で割る場合は例外が発生します。

構文

lcm(a, b)

max2

2つの値 ab のうち大きい方を返します。返される値の型は Float64 です。

構文

max2(a, b)

クエリ:

SELECT max2(-1, 2);

結果:

┌─max2(-1, 2)─┐
│           2 │
└─────────────┘

min2

2つの値 ab のうち小さい方を返します。返される値の型は Float64 です。

構文

min2(a, b)

クエリ:

SELECT min2(-1, 2);

結果:

┌─min2(-1, 2)─┐
│          -1 │
└─────────────┘

multiplyDecimal

2つの10進数 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つの10進数 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                                       │
└───────────────────────────────────────────────────────┘