如果任何行为 NULL,则 returns NULL 组内的移动平均值(雪花 - SQL)

Moving average within groups that returns NULL if any row is NULL (Snowflake - SQL)

我需要计算每组列的移动平均值(按 id 划分)。唯一的转折是,如果相应 window 中的任何值为 NULL,我需要结果为 NULL。

预期行为示例(对于给定的 id 和 window 尺寸=3):

A mov_ave_A
NULL NULL
1 NULL
1 NULL
1 1
4 2

移动平均的前3行是NULL,因为第一个值(包含在前3windows中)是NULL。 mov_ave_A 的第 4 行等于 1,因为它是 A 的第 2 行到第 4 行的平均值,依此类推。

我试过了:

CASE WHEN SUM(CASE WHEN a IS NULL THEN 1 ELSE 0 END) = 0 THEN AVG(a) ELSE NULL END
    OVER (
    PARTITION BY id
    ORDER BY date_month
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS mov_ave_A

但我明白了

"Sliding window frame unsupported for function CASE".

此外,我真的希望解决方案简短明了,因为我需要创建 6 个这样的列。所以,我必须重复逻辑 6 次。

使用以下大小写表达式:

CASE WHEN COUNT(a) OVER (
    PARTITION BY id
    ORDER BY date_month
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) = 3 THEN AVG(a) OVER (
    PARTITION BY id
    ORDER BY date_month
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) END AS mov_avg

您的查询的问题是 OVER 子句在 END 之后。我相信这应该有效。您需要为每个 window 函数设置 OVER 子句,一次用于 COUNT,一次用于 AVG。 COUNT 是一种更容易检查 NULL 的方法,然后使用 SUM

SELECT 
    *
    ,CASE
        /*Check for 3 values in a, if so return the rolling AVG value. Implicit ELSE NULL*/ 
        WHEN COUNT(a)   OVER (PARTITION BY ID ORDER BY date_month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) = 3 
        THEN AVG(a)     OVER (PARTITION BY ID ORDER BY date_month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
    END AS mov_ave_A
FROM YourTable