用户自定义函数聚合
SQL 引擎允许用户定义函数(UDF)执行自定义聚合,即与 SQL 的 group by 操作符一起使用的函数。这些用户定义的函数可以像 SQL 函数 sum()、count()、max() 等一样使用。(详情请参阅 SmartESQL 用户定义函数页面。)
要使用用户自定义的聚合函数,必须执行以下步骤:
使用 SQL 的 set 语句将参数 implicit_aggregates 设置为启用聚合函数的使用:
set implicit_aggregates=true;用 C++、Lua 或 Python 编写一个用户自定义函数(UDF)代码,该函数恰好有两个参数:state 和 ops,它们的类型均为 array(T),其中 T 为函数类型。该函数应返回一个 array(T) 类型的结果。(参数 state 应为一个内部状态变量,用于累积临时结果,而 ops 则是一个函数参数数组。)
按照以下顺序调用该 UDF:
- 首先,以 NULL 作为 state 值,ops 为非 NULL 值进行调用。此时,UDF 应创建一个状态数组,并将 ops 作为第一组值使用。状态数组作为函数结果返回。
- 接下来,以非 NULL 的 state 值和非 NULL 的 ops 值调用 UDF,以处理下一组 ops 值。
- 当数据集处理完毕后,以 NULL 作为 ops 值调用 UDF,使函数执行最终计算,并将其结果作为数组返回。
请注意,即使用户定义函数(UDF)预期接受标量参数并返回单个标量值,聚合 UDF 也必须传递数组参数并返回数组。
Lua 示例
可以使用如下 Lua 代码创建用户定义函数(UDF):
create function my_avg(state array(int), ops array(int)) returns array(int) in 'lua' as '
require("test_udf")
return my_avg_impl(state, ops)
end
';函数 my_avg_body() 可以按如下方式实现:
function my_avg_impl(state, ops)
if ops ~= nil then
-- Aggregating part
v = ops[1]
if state == nil then
state = {v, 1}
else
state[1] = state[1] + v
state[2] = state[2] + 1
end
return state
else
-- Finalizing part
local avg = {state[1] / state[2]}
return avg
end
end考虑用以下数据初始化表Employee:
create table Employee( id integer, dept_no integer, salary integer);
insert into Employee values(1, 1 90000);
insert into Employee values(2, 1 100000);
insert into Employee values(3, 1 110000);
insert into Employee values(4, 2 100000);
insert into Employee values(5, 2 120000);
insert into Employee values(6, 2 130000);然后,可以使用如下 SQL 语句调用该用户定义函数(UDF):
set implicit_aggregates=true;
select dept_no, my_avg([null]) from Employee group by dept_no;
select dept_no, my_avg([salary]) from Employee group by dept_no;
select dept_no, my_avg([null]) from Employee group by dept_no;并将返回以下结果集:
dept_no #2
--------------------------------------------------------
1 [100000]
2 [120000]C++ 示例
对于 C++ 用户定义函数(UDF),SQL 函数注册可能如下所示:
create function bx_wt_avg(state array(double), ops array(double)) returns array(double)
as 'api-sql-09-functions-aggregate', 'bx_wt_avg';对应的 C++ 函数原型可以如下所示:
McoSql::Value* bx_wt_avg(McoSql::Runtime* runtime, McoSql::Vector<McoSql::Value>* params);实际的函数实现可以在 SDK 示例源文件“samples/native/sql/api/sql-09-functions/aggregate.udf.cpp”中找到。
然后,可以使用如下 SQL 语句调用该用户定义函数(UDF):
create table t(x double,y double);
insert into t values (1,10),(2,20),(3,30);
select bx_wt_avg([x,y]) from t;并将返回以下结果集:
#1
--------------------------------------------------------
[2.33333333333333, 0.014, 140, 60, 3, 6.95335580371252e-310, 36