- 类别:
聚合函数 (通用)
ACCUMULATE¶
返回由四个用户定义的 SQL Lambda 函数(initialize、accumulate、combine 和 terminate)计算出的自定义聚合值。ACCUMULATE 遵循 MapReduce 聚合模型,并以与内置聚合函数相同的方式与 GROUP BY、HAVING 和子查询集成。
对于原型设计以及没有内置聚合函数支持的一次性聚合,ACCUMULATE 特别有用。对于性能敏感型工作负载,建议尽可能优先使用内置聚合函数,或考虑是否可以通过内置聚合函数与连接的组合来实现相同结果。使用 OBJECT、ARRAY 或 VARIANT 状态类型的 ACCUMULATE 会产生额外的性能开销。
语法¶
实参¶
input_expr对每个非 NULL 输入行求值的表达式。求得的结果值将作为输入值传递给各个 Lambda 函数。
initialize_lambda签名为
(value) -> <state_expr>的 Lambda。对每个非 NULL 输入行调用一次,根据该行的值生成初始局部状态。accumulate_lambda签名为
(state, value) -> <state_expr>的 Lambda。将新的输入值合并到现有的局部状态中,并返回更新后的状态。combine_lambda签名为
(state1, state2) -> <state_expr>的 Lambda。合并由并行工作线程生成的两个局部状态。必须满足结合律。terminate_lambda签名为
(state) -> <output_expr>的 Lambda。将最终合并的状态转换为返回给查询的结果值。
Lambda 实参名称是任意的。类型注释是可选的;有关详细信息,请参阅 类型推断。
返回¶
返回由 terminate_lambda 生成的值。数据类型与 terminate_lambda 的返回类型相匹配。如果所有输入行是 NULL 或输入集为空,则返回 NULL。
使用说明¶
在调用任何 Lambda 之前,系统会静默跳过 NULL 输入行,这与标准 SQL 聚合行为一致。如果所有输入行是 NULL 或输入集是空,则结果为 NULL。
ACCUMULATE 没有持久形式。不存在 CREATE AGGREGATE FUNCTION 或等效的 DDL。要重用聚合,请将其封装在视图、CTE 或存储过程中。
Lambda 只能引用其声明的参数。不允许引用外部查询中的列。要包含外部查询值,请将其投射到输入表达式中,或在 CTE 中预先计算。
以下示例会导致编译错误,因为
column2不是 Lambda 参数:Lambda 内部不允许使用以下函数类:
函数类
示例
聚合函数
SUM、 AVG、 COUNT
窗口函数
ROW_NUMBER() OVER (...)
非确定性函数
RANDOM(), UUID_STRING()
类型推断¶
Lambda 实参类型是可选的。如果省略,系统会从输入表达式推断类型,并沿 Lambda 链进行传递。
显式类型不会在不同的 Lambda 之间进行强制转换。如果在任何 Lambda 实参上标注了类型,该标注即为该位置状态类型的权威定义。如果四个 Lambda 之间的注释不一致且无法调和(例如
initialize返回 ARRAY,但accumulate将状态声明为 INT),则编译将失败。您可以省略所有类型注释,或仅为部分实参添加注释;编译器会自动推断并扩展类型。只要显式注释一致,就允许混合使用带注释和未注释的实参。
状态类型(在 initialize、accumulate 和 combine 之间流转的类型)与输出类型(terminate 的返回类型)会被独立跟踪,且二者可能不一致。
输入表达式会被隐式转换为 initialize Lambda 的
value实参所期望的类型。例如,如果输入列为 INT 且value声明为 STRING,则会自动执行类型转换。
示例¶
计算列的总和,模拟现有 SUM(c1) 聚合函数的等效行为:
计算组中所有值的乘积。
使用 ARRAY 跟踪运行总和与计数来计算平均值:
使用结构化 OBJECT 作为状态来计算平均值:
查找列中的最短字符串:
将 ACCUMULATE 与 GROUP BY 结合使用:
在 Lambda 内部调用 UDF: