算术函数适用于任意两个类型为 UInt8、UInt16、UInt32、UInt64、Int8、Int16、Int32、Int64、Float32 或 Float64 的操作数。
在执行运算之前,两个操作数都会转换为结果类型。结果类型按如下方式确定 (除非下文的函数文档中
另有说明) :
- 如果两个操作数都不超过 32 位宽,则结果类型的大小将取两者中较大操作数所对应类型之后的下一个更大类型
(整数类型提升) 。例如,
UInt8 + UInt16 = UInt32 或 Float32 * Float32 = Float64。
- 如果其中一个操作数为 64 位或更宽,则结果类型的大小与两个操作数中较大的那个相同。例
如,
UInt32 + UInt128 = UInt128 或 Float32 * Float64 = Float64。
- 如果其中一个操作数是有符号类型,则结果类型也将是有符号类型;否则为无符号类型。例如,
UInt32 * Int32 = Int64 或 UInt32 * UInt32 = UInt64。
这些规则可确保结果类型是能够表示所有可能结果的最小类型。虽然这会在数值范围边界附近引入
溢出的风险,但也能确保计算充分利用 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++ 中相同。
引入版本:v1.1.0
计算 x 的绝对值。如果 x 是无符号类型,则不会产生任何影响。如果 x 是有符号类型,则返回无符号数。
语法
参数
返回值
x 的绝对值
示例
使用示例
引入版本:v25.11.0
计算并返回所提供参数的平均值。
支持数值类型和时间类型。
语法
参数
x1, x2] — 接受两个用于计算平均值的参数。
返回值
返回所提供参数的平均值,并将结果提升为兼容的最大类型。
示例
数值类型
SELECT avg2(toUInt8(3), 1.0) AS result, toTypeName(result) AS type;
-- 返回类型为 Float64,因为 UInt8 必须提升为 64 位才能进行比较。
┌─result─┬─type────┐
│ 2 │ Float64 │
└────────┴─────────┘
Decimal 类型
SELECT avg2(toDecimal32(1, 2), 2) AS result, toTypeName(result) AS type;
┌─result─┬─type──────────┐
│ 1.5 │ Decimal(9, 2) │
└────────┴───────────────┘
日期类型
SELECT avg2(toDate('2025-01-01'), toDate('2025-01-05')) AS result, toTypeName(result) AS type;
┌─────result─┬─type─┐
│ 2025-01-03 │ Date │
└────────────┴──────┘
DateTime 类型
SELECT avg2(toDateTime('2025-01-01 00:00:00'), toDateTime('2025-01-03 12:00:00')) AS result, toTypeName(result) AS type;
┌──────────────result─┬─type─────┐
│ 2025-01-02 06:00:00 │ DateTime │
└─────────────────────┴──────────┘
Time64 类型
SELECT avg2(toTime64('12:00:00', 0), toTime64('14:00:00', 0)) AS result, toTypeName(result) AS type;
┌───result─┬─type──────┐
│ 13:00:00 │ Time64(0) │
└──────────┴───────────┘
引入版本:v23.10.0
将整数的字节顺序反转,即改变其字节序。
下面的示例可按以下方式理解:
- 将十进制整数转换为对应的大端十六进制格式,即 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 │
└───────────────────────────────────────────────────────┘
语法
参数
返回值
返回字节顺序颠倒后的 x。(U)Int*
示例
使用示例
SELECT byteSwap(3351772109)
8 位
16 位
32 位
SELECT byteSwap(3351772109)
64 位
SELECT byteSwap(123294967295)
引入版本:v1.1.0
计算两个值 a 和 b 的商。结果类型始终为 Float64。
整数除法请使用 intDiv 函数。
除数为 0 时,会返回 inf、-inf 或 nan。
语法
参数
返回值
x 与 y 的商
示例
两个数相除
SELECT divide(25,5) AS quotient, toTypeName(quotient)
除以零
Introduced in: v22.12.0
对两个 Decimal 执行除法运算。结果值的类型为 Decimal256。
结果标度可通过 result_scale 参数 (取值范围为 [0, 76] 的常量 Integer) 显式指定。若未指定,则结果标度为给定参数中的最大标度。
此函数的执行速度明显慢于常规的 divide。
如果你并不需要受控精度和/或需要更快的计算速度,请考虑使用 divide。
语法
divideDecimal(x, y[, result_scale])
参数
返回值
按给定标度得到的除法结果。Decimal256
示例
示例 1
divideDecimal(toDecimal256(-12, 0), toDecimal32(2.1, 1), 10)
┌─divideDecimal(toDecimal256(-12, 0), toDecimal32(2.1, 1), 10)─┐
│ -5.7142857142 │
└──────────────────────────────────────────────────────────────┘
示例 2
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 │
└─────┴─────┴────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘
在 v25.5.0 中引入
与 divide 相同,但在除数为零时返回 NULL。
语法
参数
返回值
x 与 y 的商,或 NULL。
示例
除以零
SELECT divideOrNull(25, 0)
引入版本:v1.1.0
返回两个值 a 和 b 的最大公约数。
当除数为零,或将最小负数除以负一时,
会抛出异常。
语法
参数
返回值
x 和 y 的最大公因数。
示例
使用示例
Introduced in: v20.3.0
检查浮点值是否为有限数。
你也可以使用三元运算符获得类似的结果:isFinite(x) ? x : y。
语法
参数
返回值
- 如果
x 是有限值,则返回 x。
- 如果
x 不是有限值,则返回 y。
示例
用法示例
SELECT 1/0 AS infimum, ifNotFinite(infimum,42)
Introduced in: v1.1.0
对两个值 x 和 y 执行整数除法。也就是说,
计算向下取整后的商。
结果与被除数 (第一个参数) 的位宽相同。
当除以零、商超出被除数的取值范围,或将最小负数除以负一时,
会抛出异常。
语法
参数
返回值
x 与 y 整数相除的结果
示例
两个浮点数的整数除法
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)
引入版本:v25.5.0
与 intDiv 相同,但在除数为零或将最小负数除以负一时返回 NULL。
语法
参数
返回值
x 与 y 做整数除法的结果,或 NULL。
示例
被零除的整数除法
SELECT intDivOrNull(1, 0)
最小负数除以 -1
SELECT intDivOrNull(-9223372036854775808, -1)
引入版本:v1.1.0
与 intDiv 相同,但在除数为零,或将最小负数除以负一时返回零。
语法
参数
返回值
a 与 b 做整数除法的结果,或为零。
示例
整数除以零
SELECT intDivOrZero(1, 0)
最小负数除以 -1
SELECT intDivOrZero(0.05, -1)
引入版本:v1.1.0
如果 Float32 或 Float64 参数既不是无穷大也不是 NaN,则返回 1,
否则返回 0。
语法
参数
返回值
如果 x 不是无穷大且不是 NaN,则返回 1;否则返回 0。
示例
测试一个数是否为有限值
Introduced in: v1.1.0
如果 Float32 或 Float64 参数是无穷大,则返回 1;否则返回 0。
请注意,参数为 NaN 时也会返回 0。
Syntax
参数
返回值
若 x 为无穷大,则返回 1;否则返回 0 (NaN 也返回 0) 。
示例
判断一个数值是否为无穷大
SELECT isInfinite(inf), isInfinite(NaN), isInfinite(10))
引入版本:v1.1.0
如果 Float32 或 Float64 类型的参数为 NaN,则返回 1,否则返回 0。
语法
参数
返回值
如果为 NaN,则返回 1;否则返回 0
示例
使用示例
引入版本:v1.1.0
返回两个值 x 和 y 的最小公倍数。
当除以零,或将最小负数除以负一时,会抛出异常。
语法
参数
返回值
返回 x 和 y 的最小公倍数。(U)Int*
示例
用法示例
引入版本:v21.11.0
返回两个数值 x 和 y 中较大的值。
语法
参数
返回值
返回 x 和 y 中的较大值。 Float64
示例
用法示例
引入版本:v25.11.0
计算并返回给定参数的平均值。
支持数值类型和时间类型。
语法
参数
x1[, x2, ...] — 接受单个值或多个值,并对其求平均值。
返回值
返回所提供参数的平均值,结果会提升为兼容的最大类型。
示例
数值类型
SELECT midpoint(1, toUInt8(3), 0.5) AS result, toTypeName(result) AS type;
-- 返回类型为 Float64,因为 UInt8 必须提升为 64 位才能进行比较。
┌─result─┬─type────┐
│ 1.5 │ Float64 │
└────────┴─────────┘
Decimal 类型
SELECT midpoint(toDecimal32(1.5, 2), toDecimal32(1, 1), 2) AS result, toTypeName(result) AS type;
┌─result─┬─type──────────┐
│ 1.5 │ Decimal(9, 2) │
└────────┴───────────────┘
日期类型
SELECT midpoint(toDate('2025-01-01'), toDate('2025-01-05')) AS result, toTypeName(result) AS type;
┌─────result─┬─type─┐
│ 2025-01-03 │ Date │
└────────────┴──────┘
DateTime 类型
SELECT midpoint(toDateTime('2025-01-01 00:00:00'), toDateTime('2025-01-03 12:00:00')) AS result, toTypeName(result) AS type;
┌──────────────result─┬─type─────┐
│ 2025-01-02 06:00:00 │ DateTime │
└─────────────────────┴──────────┘
Time64 类型
SELECT midpoint(toTime64('12:00:00', 0), toTime64('14:00:00', 0)) AS result, toTypeName(result) AS type;
┌───result─┬─type──────┐
│ 13:00:00 │ Time64(0) │
└──────────┴───────────┘
引入版本:v21.11.0
返回两个数值 x 和 y 中较小的一个。
语法
参数
返回值
返回 x 和 y 中较小的值。 Float64
示例
使用示例
在 v1.1.0 中引入
计算两个值 a 和 b 的差值。结果始终为带符号数。
与 plus 类似,也可以用日期或日期时间减去一个整数。
此外,也支持两个日期时间相减,结果为它们之间的时间差。
语法
参数
返回值
x 与 y 的差
示例
两个数相减
整数和日期相减
SELECT minus(toDate('2025-01-01'),5)
Introduced in: v1.1.0
计算两个值 a 除以 b 所得的余数。
如果两个输入都是整数,结果类型为整数。如果其中一个输入是浮点数,结果类型则为 Float64。
余数的计算方式与 C++ 相同。对于负数,使用截断除法。
当除数为零,或将最小负数除以负一时,会抛出异常。
Syntax
别名: mod
参数
返回值
a % b 的余数
示例
使用示例
引入版本:v1.1.0
计算除法的余数。这是使用 C++ % 运算符的旧版取模实现,对于负参数,可能会产生负结果。保留此函数是为了兼容旧版表分区逻辑。标准行为请使用 modulo 或 positiveModulo。
语法
参数
返回值
返回相除后的余数。(U)Int* 或 Float*
示例
基本用法
SELECT moduloLegacy(10, 3)
引入版本:v25.5.0
计算 a 除以 b 的余数。与函数 modulo 类似,不同之处在于当右侧参数为 0 时,moduloOrNull 会返回 NULL。
语法
别名: modOrNull
参数
返回值
返回 x 除以 y 的余数;当除数为零时,返回 NULL。
示例
除数为零时的 moduloOrNull
SELECT moduloOrNull(5, 0)
首次引入版本:v20.3.0
与 modulo 类似,但当除数为零时会返回零,而不是像
modulo 函数那样抛出异常。
语法
参数
返回值
返回 a % b 的余数;当除数为 0 时,返回 0。
示例
使用示例
SELECT moduloOrZero(5, 0)
引入于:v1.1.0
计算两个值 x 和 y 的乘积。
语法
参数
返回值
返回 x 与 y 的乘积
示例
将两个数相乘
引入版本:v22.12.0
对两个 Decimal 执行乘法。结果值的类型为 Decimal256。
结果标度可以通过 result_scale 参数 (取值范围为 [0, 76] 的常量 Integer) 显式指定。若未指定,则结果标度为给定参数中的最大标度。
这些函数的运行速度明显慢于常规的 multiply。
如果你并不需要受控精度和/或希望快速计算,请考虑使用 multiply
语法
multiplyDecimal(a, b[, result_scale])
参数
返回值
按给定标度计算出的乘法结果。类型:Decimal256
示例
使用示例
SELECT multiplyDecimal(toDecimal256(-12, 0), toDecimal32(-2.1, 1), 1)
与普通乘法的区别
SELECT multiplyDecimal(toDecimal256(-12, 0), toDecimal32(-2.1, 1), 1)
┌─multiply(toDecimal64(-12.647, 3), toDecimal32(2.1239, 4))─┐
│ -26.8609633 │
└───────────────────────────────────────────────────────────┘
┌─multiplyDecimal(toDecimal64(-12.647, 3), toDecimal32(2.1239, 4))─┐
│ -26.8609 │
└──────────────────────────────────────────────────────────────────┘
Decimal 类型溢出
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)
引入版本:v1.1.0
对参数 x 取反。结果始终为有符号数。
语法
参数
返回值
返回 x 的相反数 -x。
示例
使用示例
引入版本:v1.1.0
计算两个值 x 和 y 的和。别名:x + y (运算符) 。
整数可以与日期或日期时间相加。前一种
运算会增加日期中的天数,后一种运算
会增加日期时间中的秒数。
日期也可以与时间相加。将 Date 与 Time
相加会生成 DateTime。将 Date 与 Time64 相加,或将 Date32 与
Time 或 Time64 相加,会生成 DateTime64。
语法
参数
返回值
返回 x 与 y 的和
示例
两个数相加
整数与日期相加
SELECT plus(toDate('2025-01-01'),5)
添加日期和时间
SELECT toDate('2025-01-01') + CAST('14:30:25', 'Time')
引入版本:v22.11.0
计算 x 除以 y 的余数。与函数
modulo 类似,不同之处在于 positiveModulo 始终返回非负数。
语法
别名: positive_modulo, pmod
参数
返回值
返回 x 与不大于 x 且能被 y 整除的最大整数之间的差值。
示例
用法示例
SELECT positiveModulo(-1, 10)
引入版本:v25.5.0
计算 a 除以 b 的余数。与函数 positiveModulo 类似,不同之处在于,如果右侧参数为 0,positiveModuloOrNull 将返回 NULL。
语法
positiveModuloOrNull(x, y)
别名: positive_modulo_or_null, pmodOrNull
参数
返回值
返回 x 与不大于 x 且可被 y 整除的最大整数之差;当除数为零时,返回 null。
示例
positiveModuloOrNull
SELECT positiveModuloOrNull(5, 0)