如何克服 Snowflake SQL UDTF 相关子查询错误?

Posted

技术标签:

【中文标题】如何克服 Snowflake SQL UDTF 相关子查询错误?【英文标题】:How to get past Snowflake SQL UDTF correlated subquery error? 【发布时间】:2020-07-08 11:22:54 【问题描述】:

我定义了以下 UDTF,我已确认查询与函数分开工作。

CREATE OR REPLACE FUNCTION UDF_RETAINED_CUST(period_end date)
    RETURNS TABLE(RETAINED_CUSTOMERS number)
    LANGUAGE SQL 
    AS 
    $$
    SELECT count(DISTINCT po.id_customer)
    FROM STR_PS_ORDERS po
    INNER JOIN (
        SELECT DISTINCT ID_CUSTOMER 
        FROM STR_PS_ORDERS po
        WHERE CURRENT_STATE NOT IN (6, 7, 8)
        AND ORDER_TYPE_ID NOT IN (2, 7)
        AND DATE_ADD >= dateadd(DAY, -181, period_end)
        AND DATE_ADD <= dateadd(DAY, -91, period_end)
    ) prev ON prev.id_customer = po.ID_CUSTOMER 
    WHERE CURRENT_STATE NOT IN (6, 7, 8)
    AND ORDER_TYPE_ID NOT IN (2, 7)
    AND DATE_ADD >= dateadd(DAY, -90, period_end)
    AND DATE_ADD <= period_end
    $$

我也可以用单个值成功运行函数

SELECT * FROM TABLE(UDF_RETAINED_CUST(CURRENT_DATE()))

问题是在尝试将此函数与来自另一个表的列输入一起使用时。

SELECT dd.DATE_SPK, x.retained_customers
FROM DIM_DATE dd 
JOIN TABLE(UDF_RETAINED_CUST(dd.DATE_SPK))) x

这会提示如下错误:

SQL 错误 [2031] [42601]:SQL 编译错误: 无法评估不受支持的子查询类型

【问题讨论】:

尝试使用 WITH 您的意思是在函数内部使用 CTE,还是代替 UDF? 【参考方案1】:

使用 UDF 时请记住,它们本身并不是函数。在运行时它们被解包并且代码用于替换原始查询 - 因此,为了确保您的函数能够正常工作,您可以通过简单地将那段代码放入主查询并查看它的编译方式来测试它,即:

FROM DIM_DATE dd 
JOIN 
    SELECT count(DISTINCT po.id_customer)
    FROM STR_PS_ORDERS po
    INNER JOIN (
        SELECT DISTINCT ID_CUSTOMER 
        FROM STR_PS_ORDERS po
        WHERE CURRENT_STATE NOT IN (6, 7, 8)
        AND ORDER_TYPE_ID NOT IN (2, 7)
        AND DATE_ADD >= dateadd(DAY, -181, dd.DATE_SPK)
        AND DATE_ADD <= dateadd(DAY, -91, dd.DATE_SPK)
    ) prev ON prev.id_customer = po.ID_CUSTOMER 
    WHERE CURRENT_STATE NOT IN (6, 7, 8)
    AND ORDER_TYPE_ID NOT IN (2, 7)
    AND DATE_ADD >= dateadd(DAY, -90, dd.DATE_SPK)
    AND DATE_ADD <= period_end) x

在您的情况下,问题似乎出在函数中的相关子查询中 - Snowflake 中的子查询的使用非常有限,并且(除其他外)此类子查询仅允许返回单个结果,而不管值如何参与。

要完成这项工作,您需要重写查询以消除子查询中的相关性

【讨论】:

感谢您的回复。你有一个如何在主查询中测试代码的例子吗?由于该函数适用于单个值,我会认为查询是有效的。此外,函数中的子查询没有对外部查询的任何引用,所以它仍然相关吗? 你在那里使用 dd.DATE_SPK,所以它肯定是相关的。并将示例放在主要答案中,因为评论太长了

以上是关于如何克服 Snowflake SQL UDTF 相关子查询错误?的主要内容,如果未能解决你的问题,请参考以下文章

我们可以在 UDTF 中使用标识符函数,其参数来自 Snowflake 中的 UDTF 参数吗?

如何克服 Snowflake Varchar (16,777,216) 加载图像数据的限制

如何在 Snowflake 中编写等效的 IF ELSE adhoc sql 查询

如何使用 Snowflake sql 查询的结果填充 pandas DataFrame?

Snowflake SQL:如何使用 JSON 对象循环遍历数组,以查找符合条件的项目

阅读方法: 如何克服默读