如何在雪花 SQL 查询中动态调用过程/函数?

时间:2021-02-27 19:21:59

标签: sql sql-server snowflake-cloud-data-platform

到目前为止,在 StackOverflow 上关于这个话题的内容很少,没有任何东西能帮助我解决这个问题。我一直试图在一个简单的雪花选择查询中调用一个函数,粘贴在下面。我不断收到的错误是:“无法评估不受支持的子查询类型”。我也尝试过使用存储过程,但我似乎无法弄清楚。

SELECT  CUST.CUSTID , GET_ORD_COUNT(CUST.CUSTID , 0,10)
FROM SALES.CUSTOMERS AS CUST

我尝试使用的函数:

CREATE OR REPLACE FUNCTION GET_ORD_COUNT(CUSTID INT, COUNT_FROM INT, COUNT_TO INT)
RETURNS INTEGER
LANGUAGE SQL
AS $$
SELECT TOP 1 COUNT(*)
from(
SELECT  ORD1.ORDERID , ORD1.CUSTID, ORD1.ORDERDATE, MIN(ORD2.ORDERDATE) AS ORDERDATE2, DATEDIFF("D", ORD1.ORDERDATE , MIN(ORD2.ORDERDATE)) AS DaysDiff
FROM    SALES.ORDERS ORD1
LEFT JOIN SALES.ORDERS ORD2 ON ORD1.CUSTID = ORD2.CUSTID AND ORD2.ORDERDATE > ORD1.ORDERDATE
GROUP BY ORD1.ORDERID, ORD1.CUSTID , ORD1.ORDERDATE
HAVING DAYSDIFF IS NOT NULL
ORDER BY ORD1.CUSTID, ORD1.ORDERDATE 
) AS SALES_COUNT 
WHERE SALES_COUNT.DAYSDIFF <= COUNT_TO AND SALES_COUNT.DAYSDIFF >= COUNT_FROM AND SALES_COUNT.CUSTID = CUSTID
GROUP BY SALES_COUNT.CUSTID
$$;

该函数可以很好地处理硬编码值,但对我来说没有用。

1 个答案:

答案 0 :(得分:1)

因此从过程更改为 CTE,我们将独立于变量的函数内部移动到 CTE sales_count 然后我们有第二个 CTE cust_data 纯粹用于演示目的,好像这些值不会改变,应该被移动到“函数”中,这意味着它们可以改变,从而允许它们被改变,当这使用存在于函数外部的逻辑连接两个数据集时。

WITH sales_count AS (
    SELECT  ord1.orderid 
        ,ord1.custid
        ,ord1.orderdate
        ,MIN(ord2.orderdate) AS orderdate2
        ,DATEDIFF("D", ord1.orderdate , MIN(ord2.orderdate)) AS daysdiff
    FROM sales.orders AS ord1
    LEFT JOIN sales.orders AS ord2 
        ON ord1.custid = ord2.custid AND ord2.orderdate > ord1.orderdate
    GROUP BY ord1.orderid, ord1.custid, ord1.orderdate
    HAVING daysdiff IS NOT NULL
), cust_data AS (
    SELECT cust.custid
        ,0 AS count_from
        ,10 AS count_to
    FROM sales.customers AS cust
)
SELECT c.custid
    ,c.count_from
    ,c.count_to
    ,count(*) AS count
FROM cust_data AS c
JOIN sales_count AS s 
    ON s.custid = c.custid AND s.daysdiff <= c.count_to AND s.daysdiff >= c.count_from 
GROUP BY 1,2,3;

CTE sales_count 可以从选择中删除 ord1.orderid,因为它没有在连接中使用,并且因为它按顺序显式命名,它提供了值(在本问题中),因此可以是:

WITH sales_count AS (
    SELECT  ord1.custid
        ,ord1.orderdate
        ,MIN(ord2.orderdate) AS orderdate2
        ,DATEDIFF("D", ord1.orderdate , MIN(ord2.orderdate)) AS daysdiff
    FROM sales.orders AS ord1
    LEFT JOIN sales.orders AS ord2 
        ON ord1.custid = ord2.custid AND ord2.orderdate > ord1.orderdate
    GROUP BY ord1.orderid, ord1.custid, ord1.orderdate
    HAVING daysdiff IS NOT NULL
)