在 Databricks / Spark 中的 SQL 中为变量分配动态值

Phi*_*ahn 10 apache-spark apache-spark-sql databricks

我觉得我一定在这里遗漏了一些明显的东西,但我似乎无法在 Spark SQL 中动态设置变量值。

假设我有两个表tableSrc和,tableBuilder并且我正在创建tableDest。

我一直在尝试变体

SET myVar FLOAT = NULL

SELECT
    myVar = avg(myCol)
FROM tableSrc;

CREATE TABLE tableDest(
    refKey INT,
    derivedValue FLOAT
);


INSERT INTO tableDest
    SELECT
        refKey,
        neededValue * myVar AS `derivedValue`
    FROM tableBuilder
Run Code Online (Sandbox Code Playgroud)

在 T-SQL 中执行此操作是微不足道的,这对 Microsoft 来说是一个令人惊讶的胜利(DECLARE... SELECT)。然而,Spark 抛出

Error in SQL statement: ParseException: mismatched input 'SELECT' expecting <EOF>(line 53, pos 0)

但我似乎无法将派生值分配给变量以供重用。我尝试了几种变体,但最接近的是将变量分配给 select 语句的字符串。

数据块截图

请注意,这是根据 T-SQL 中的功能齐全的脚本改编的,因此我不会尽快拆分出十几个 SQL 变量来使用 Python Spark 查询来计算所有这些变量,只是为了在中插入{var1}、{var2}等数百行 f 字符串。我知道如何做到这一点,但它会很混乱、困难、难以阅读、迁移速度较慢、维护更差,并且希望尽可能避免这种情况。

Ron*_*ues 23

使用的SET命令用于spark.conf get/set,而不是用于SQL查询的变量

对于 SQL 查询,您应该使用小部件:

https://docs.databricks.com/notebooks/widgets.html

但是,有一种在 SQL 上使用 Spark.conf 参数的方法:

%python spark.conf.set('personal.foo','bar')

然后你可以使用:

$sql select * from table where column = '${personal.foo}';

技巧部分是你必须在spark.conf的名称上使用“点”(或其他特殊字符),否则SQL单元会期望你在运行时为$变量提供值(它看起来像一个错误)对我来说,我相信用 {} 舍入应该足够了)

  • 喜欢 `spark.conf.set(....)` 这对我的笔记本来说会很棒。感谢您发帖。 (2认同)

mat*_*rek 9

Databricks 刚刚发布了SQL 用户定义函数,它可以处理类似的问题而不会造成性能损失,对于您的示例,它看起来像:

CREATE TEMP FUNCTION myVar()
RETURNS FLOAT
LANGUAGE SQL
RETURN 
SELECT
    avg(myCol)
FROM tableSrc;
Run Code Online (Sandbox Code Playgroud)

然后使用:

SELECT
      refKey,
      neededValue * myVar() AS `derivedValue`
FROM tableBuilder
Run Code Online (Sandbox Code Playgroud)