如何克服 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 相关子查询错误?的主要内容,如果未能解决你的问题,请参考以下文章