常规函数
函数至少有*两种类型 —— 常规函数(通常就直接称为“函数”)和聚合函数。这是完全不同的概念。常规函数的工作方式就像是对每一行单独应用(对于每一行,函数的结果不依赖于其他行)。聚合函数则会从多行中累积一组值(即它们依赖于整组行)。
本节讨论的是常规函数。关于聚合函数,请参阅“聚合函数”一节。
强类型
与标准 SQL 不同,ClickHouse 使用强类型。换句话说,它不会在类型之间进行隐式转换。每个函数仅适用于特定的一组类型。因此,有时需要使用类型转换函数。
公共子表达式消除
查询中所有具有相同 AST(相同的抽象语法树结构或相同的语法解析结果)的表达式都被视为具有相同的值。此类表达式会被合并后只执行一次。相同的子查询也会以这种方式被消除。
结果类型
所有函数都返回单个值作为结果(既不会返回多个值,也不会不返回值)。结果类型通常仅由参数类型决定,而不是由参数值决定。例外是 tupleElement 函数(a.N 运算符)和 toFixedString 函数。
常量
为简化处理,某些函数在部分参数上只能使用常量。例如,LIKE 运算符的右侧参数必须是常量。
几乎所有函数在其参数是常量时都会返回常量。例外是生成随机数的函数。
now 函数对于在不同时间运行的查询会返回不同的值,但结果仍被视为常量,因为是否为常量只在单个查询内部才重要。
常量表达式也被视为常量(例如,LIKE 运算符的右半部分可以由多个常量拼接而成)。
对于常量参数和非常量参数,函数可以采用不同的实现方式(执行不同的代码)。但是,对于一个常量和一个仅包含相同值的实际列,它们的计算结果应当一致。
NULL 处理
函数具有以下行为:
- 如果函数的至少一个参数为
NULL,则函数结果也为NULL。 - 某些函数具有在各自描述中单独说明的特殊行为。在 ClickHouse 源代码中,这些函数将
UseDefaultImplementationForNulls设为false。
不变性
函数不能更改其参数的值——任何修改都会通过返回结果体现出来。因此,单独计算各个函数的结果与这些函数在查询中的书写顺序无关。
高阶函数
-> 运算符和 lambda(params, expr) 函数
高阶函数只能接受 lambda 函数作为其函数型参数。要将 lambda 函数传递给高阶函数,请使用 -> 运算符。箭头左侧是形式参数,可以是任意 ID,或者多个形式参数——元组中的任意 ID。箭头右侧是一个表达式,该表达式可以使用这些形式参数以及任意表的列。
示例:
接收多个参数的 lambda 函数也可以作为参数传递给高阶函数。在这种情况下,会将若干长度相同的数组传递给高阶函数,这些参数分别对应这些数组中的元素。
对于某些函数,可以省略第一个参数(lambda 函数)。在这种情况下,默认认为执行的是恒等映射。
用户自定义函数(UDF)
ClickHouse 支持用户自定义函数(UDF)。请参阅用户自定义函数(UDF)。