如果任何行为 NULL,则组内的移动平均值返回 NULL(Snowflake - SQL)

发布于 2025-01-12 20:01:51 字数 910 浏览 1 评论 0原文

我需要计算每组列的移动平均值(按id分区)。唯一的问题是,如果相应窗口中的任何值为 NULL,我需要结果为 NULL。

预期行为示例(对于给定的 id 和窗口大小=3):

Amov_ave_A
NULLNULL
1NULL
1NULL
11
42

移动平均值的前 3 行为 NULL,因为第一个值(包含在前 3 个窗口中)为 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

但我明白了

“功能 CASE 不支持滑动窗框”。

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

I need to caluclate the moving average of a column per group (partitioned by id). The only twist is that I need the result to be NULL if any value in the corresponding window is NULL.

Example of expected behaviour (for a given id and window size=3):

Amov_ave_A
NULLNULL
1NULL
1NULL
11
42

The first 3 rows of the moving average are NULL, because the first value (which is included in the first 3 windows) is NULL. Row 4 of mov_ave_A is equal to 1 because it's the average of rows 2 to 4 of A, and so on.

I tried:

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

but I get

"Sliding window frame unsupported for function CASE".

Also, I'd really like the solution to be short and simple as I need to create 6 such columns. So, I'll have to repeat the logic 6 times.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

缘字诀 2025-01-19 20:01:51

您的查询的问题是 OVER 子句位于 END 之后。我相信这应该有效。每个窗口函数都需要有 OVER 子句,一次用于 COUNT,一次用于 AVG。 COUNT 是比使用 SUM 检查 NULL 更简单的方法

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

The issue with your query is the OVER clause is after the END. I believe this should work. You need to have the OVER clause for each window function so once for COUNT and once for AVG. COUNT is a easier to way to check for NULL's then using 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
愁杀 2025-01-19 20:01:51

使用以下 case 表达式:

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

Use the following case expression:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文