我的问题是:
如何在Bigquery UDF中传递函数作为参数?
我想从两组私有函数创建一个bigquery udf库:
- functionA, functionB, functionC
- function1, function2, function3
我想公开从两个集合的每个函数组合构建的mixin udf。
我想避免源代码中的代码重复。
到目前为止,我找到的两个解决方案是:
解决方案1:
在函数内部使用一个唯一的公共UDF,带有两个字符串参数和一个开关箱。
例如:
mypublic_UDF(*args, "functionA", "function1")
mypublic_UDF(*args, "functionA", "function3")
mypublic_UDF(*args, "functionB", "function1")
然而,这个解决方案没有从bigquery SQL自省、预运行错误和警告检查中获益,并且涉及对每行的参数进行解析。
解决方案2:
使用在新函数中实例化每种情况的部署脚本
例如:
mypublic_UDF_functionA_function1(*args)
mypublic_UDF_functionA_function3(*args)
mypublic_UDF_functionB_function1(*args)
然而,这个解决方案需要更多的逻辑来部署脚本和生成大量的函数。
是否有首选/最佳解决方案?
编辑:
我的代码太复杂了,不能在这里展示,但这里有一个具体的例子。
CREATE TEMP FUNCTION functionA (myint NUMERIC)
AS (IF( mod(myint,3)=1, myint, NULL));
CREATE TEMP FUNCTION functionB (myint NUMERIC)
AS (IF( mod(myint,4)>3, myint, NULL));
CREATE TEMP FUNCTION functionC (myint NUMERIC)
AS (IF( mod(myint*myint-1,5)=0, myint, NULL));
CREATE TEMP FUNCTION function1 (myint NUMERIC)
AS (SQRT(ABS(myint)));
CREATE TEMP FUNCTION function2 (myint NUMERIC)
AS (LEAST(GREATEST(myint,-1),1));
CREATE TEMP FUNCTION function3 (myint NUMERIC)
AS (1/GREATEST(myint,1));
--------------------------------------------------------
-- SOLUTION 1
--------------------------------------------------------
CREATE TEMP FUNCTION first_functionset
(myint NUMERIC, mytype STRING)
AS (
CASE mytype
WHEN 'functionA' THEN functionA(myint)
WHEN 'functionB' THEN functionB(myint)
WHEN 'functionC' THEN functionC(myint)
ELSE ERROR('Unknown function name')
END
);
CREATE TEMP FUNCTION second_functionset
(myint NUMERIC, mytype STRING)
AS (
CASE mytype
WHEN 'function1' THEN function1(myint)
WHEN 'function2' THEN function2(myint)
WHEN 'function3' THEN function3(myint)
ELSE ERROR('Unknown function name')
END
);
CREATE TEMP FUNCTION mypublic_UDF
(myarray ARRAY<INT64>, param1 STRING, param2 STRING)
AS ((SELECT array_agg(first_functionset(second_functionset(x,param2),param1) IGNORE NULLS)
from
unnest(myarray) x
));
--------------------------------------------------------
-- SOLUTION 2
--------------------------------------------------------
CREATE TEMP FUNCTION mypublic_UDF_functionA_function1
(myarray ARRAY<INT64>)
AS ((SELECT array_agg(functionA(function1(x)) IGNORE NULLS)
from
unnest(myarray) x
));
CREATE TEMP FUNCTION mypublic_UDF_functionA_function2
(myarray ARRAY<INT64>)
AS ((SELECT array_agg(functionA(function2(x)) IGNORE NULLS)
from
unnest(myarray) x
));
CREATE TEMP FUNCTION mypublic_UDF_functionA_function3
(myarray ARRAY<INT64>)
AS ((SELECT array_agg(functionA(function3(x)) IGNORE NULLS)
from
unnest(myarray) x
));
CREATE TEMP FUNCTION mypublic_UDF_functionB_function1
(myarray ARRAY<INT64>)
AS ((SELECT array_agg(functionB(function1(x)) IGNORE NULLS)
from
unnest(myarray) x
));
-- and so on
Select
-- SOLUTION 1
mypublic_UDF(GENERATE_ARRAY(0,100), 'functionA', 'function1'),
mypublic_UDF(GENERATE_ARRAY(0,100), 'functionA', 'function3'),
mypublic_UDF(GENERATE_ARRAY(0,100), 'functionB', 'function1'),
-- SOLUTION 2
mypublic_UDF_functionA_function1(GENERATE_ARRAY(0,100)),
mypublic_UDF_functionA_function3(GENERATE_ARRAY(0,100)),
mypublic_UDF_functionB_function1(GENERATE_ARRAY(0,100)),
它将适用于解决方案1:一个函数具有不同的参数。然而,可读性也很重要。您能否将6个内部函数的查询分别放入单独的udf中?主mypublic_UDF
总是可以调用其中的两个。
请随意在您的UDF中给出,我将为改进bigquery SQL自省添加这个答案。