在使用 Spark SQL 的 Databricks 工作簿中,如何通过 SQL UDF 函数传递参数?

In Databricks Workbook using Spark SQL, how to pass parameters thru SQL UDF functions?

提问人:Trevor C 提问时间:11/14/2023 最后编辑:Alex OttTrevor C 更新时间:11/14/2023 访问量:64

问:

以前发布在 Databricks Community: https://community.databricks.com/t5/community-discussions/can-we-pass-parameters-thru-sql-udf-s/td-p/50752

是否可以将参数从一个 SQL UDF 传递到第一个 SQL UDF 调用的另一个 SQL UDF?

下面是一个示例,我想通过将 tbl_func.a_val 参数传递给 tbl_filter() 从 tbl_func() 调用 tbl_filter()。

显然,我只能在一个函数中实现逻辑,但在我的用例中,这意味着在不同版本的 tbl_func() 中一遍又一遍地重复查询的 tbl_filter() 部分,这违背了将代码打包到函数中的目的。理想情况下,将有一个 tbl_filter() 版本需要维护,可以使用我传递给 tabl_func() 的任何参数从各种不同版本的 tbl_func() 调用该版本。

如果没有,解决此类问题的解决方法是什么?

CREATE OR REPLACE TEMPORARY VIEW test_tbl AS
WITH a AS
(SELECT explode(sequence(1, 10)) AS a),
b AS
(SELECT explode(sequence(50, 60)) AS b)
SELECT * FROM a CROSS JOIN b;

CREATE OR REPLACE TEMPORARY FUNCTION tbl_filter(a_val INT)
    RETURNS TABLE(a INT, b INT)
    RETURN
    SELECT * FROM test_tbl tf
    WHERE tf.a = tbl_filter.a_val;

CREATE OR REPLACE TEMPORARY FUNCTION tbl_func(a_val INT, b_val INT)
    RETURNS TABLE(a INT, b INT)
    RETURN
    SELECT * FROM tbl_filter(tbl_func.a_val) tf
    WHERE tf.b = tbl_func.b_val;

-- This executes
-- select * from tbl_filter(1);

-- This does not: Error in SQL statement: AnalysisException: could not resolve `tbl_filter` to a table-valued function.
select * from tbl_func(1, 60);
apache-spark apache-spark-sql 用户定义函数 databricks-sql

评论


答:

1赞 Chen Hirsh 11/14/2023 #1

使用临时函数时,该函数仅适用于当前会话。显然,tbl_func 函数中的内部 SQL 代码使用不同的会话,无法解析名称。

最简单的解决方案是使用永久函数和视图:

CREATE OR REPLACE VIEW mydb.test_tbl AS
WITH a AS
(SELECT explode(sequence(1, 10)) AS a),
b AS
(SELECT explode(sequence(50, 60)) AS b)
SELECT * FROM a CROSS JOIN b;

CREATE OR REPLACE FUNCTION mydb.tbl_filter(a_val INT)
    RETURNS TABLE(a INT, b INT)
    RETURN
    SELECT * FROM mydb.test_tbl tf
    WHERE tf.a = tbl_filter.a_val;

CREATE OR REPLACE FUNCTION mydb.tbl_func(a_val INT, b_val INT)
    RETURNS TABLE(a INT, b INT)
    RETURN
    SELECT * FROM mydb.tbl_filter(tbl_func.a_val) tf
    WHERE tf.b = tbl_func.b_val;

-- This executes
select * from mydb.tbl_filter(1);

-- This also executes
select * from mydb.tbl_func(1, 60);

query_results