在雪花中对具有不同大小的移动窗口的数字列求和

Posted

技术标签:

【中文标题】在雪花中对具有不同大小的移动窗口的数字列求和【英文标题】:Summing over a numeric column with moving window of varying size in Snowflake 【发布时间】:2021-08-21 00:17:54 【问题描述】:

我有一个示例数据集,如下所示;

time  |  time_diff  | amount
time1 |  time1-time2 | 1000
time2 |  time2-time3 | 2000
time3 |  time3-time4 | 3000
time4 |  time4-time5 | 4500
time5 |   NULL       | 1000

快速解释;第一列给出交易时间,第二列给出与下一行的差异以获得交易间隔(以小时为单位),第三列给出在特定交易中赚到的钱。我们已经使用时间列按升序对数据进行了排序。

一些值被给出为;

time  |  time_diff  | amount
time1 |  2.         | 1000
time2 |  3.         | 2000
time3 |  1.         | 3000
time4 |  19.        | 4500
time5 |   NULL       | 1000

目标是找出给定时间内的总交易量,该交易发生在该交易的 24 小时内。例如,time1 shd 的输出是; 1000+2000+3000=6000。因为如果我们在 time4 的值相加,总的时间间隔变成 25,因此我们从总和中省略了 4500 的值。

示例输出

time  |  amount
time1 | 6000       
time2 | 9500         
time3 | 7500         
time4 | 4500        
time5 | 1000

据我所知,Mong 窗口总和的概念应该有效,但这里窗口的宽度是可变的。这就是我面临的挑战。我可以在这里得到一些帮助吗?

【问题讨论】:

我不明白您的 timediff 列是如何工作的。可能更容易为“时间”提供真实值? 【参考方案1】:

您可以忽略 time_diff 列并使用基于时间戳范围的 theta 自连接,如下所示:

WITH srctab AS (    SELECT TO_TIMESTAMP_NTZ('2020-04-15 00:00:00') AS "time", 1000::INT AS "amount"
          UNION ALL SELECT TO_TIMESTAMP_NTZ('2020-04-15 00:02:00'), 2000::INT
          UNION ALL SELECT TO_TIMESTAMP_NTZ('2020-04-15 00:05:00'), 3000::INT
          UNION ALL SELECT TO_TIMESTAMP_NTZ('2020-04-15 00:06:00'), 4500::INT
          UNION ALL SELECT TO_TIMESTAMP_NTZ('2020-04-16 00:01:00'), 1000::INT
          )
SELECT t1."time", SUM(t2."amount") AS tot
FROM srctab t1
JOIN srctab t2 ON t2."time" BETWEEN t1."time" AND TIMESTAMPADD(HOUR, +24, t1."time")
GROUP BY t1."time"
ORDER BY t1."time";

次要细节:如果您的第二列给出了与 next 行的时间差,那么我会说第一个值应该是 10500(而不是 6000),因为这只是您的 1000 的第 5 笔交易提前超过 24 小时...我猜你的实际时间戳是 0、2、5、6 和 25 小时?

【讨论】:

【参考方案2】:

另一种选择可能是使用sliding WINDOW 函数,方法是调整您的交易数据以包含每小时。

这可能是一种矫枉过正,但可能是一种有用的技术。

首先使用时间戳为每个小时生成一个占位符。我使用time_slice 将每个时间戳映射到美好的小时块中,并使用generator 和dateadd 来回填每个小时,在没有交易发生的地方放置一个零。

所以现在我可以使用滑动窗口功能,因为我知道我可以安全地选择前 23 个小时。

复制|粘贴|运行

WITH SRCTAB AS (
SELECT  TO_TIMESTAMP_NTZ('2020-04-15 00:00:00') AS TRANS_TS,   1000::INT AS AMOUNT
UNION ALL   SELECT  TO_TIMESTAMP_NTZ('2020-04-15 02:00:00'),  2000::INT
UNION ALL SELECT  TO_TIMESTAMP_NTZ('2020-04-15 05:00:00'), 3000::INT
UNION ALL SELECT TO_TIMESTAMP_NTZ('2020-04-15 06:00:00'),  4500::INT
UNION ALL  SELECT  TO_TIMESTAMP_NTZ('2020-04-16 01:00:00'), 1000::INT
)
SELECT 
    TRANS_TIME_HOUR 
    ,SUM(AMOUNT) OVER ( ORDER BY TRANS_TIME_HOUR ROWS BETWEEN 23 PRECEDING AND 0 PRECEDING ) OVERKILL FROM (
SELECT
    TRANS_TIME_HOUR,
    SUM(AMOUNT) AMOUNT
FROM
    (
    SELECT
        DATEADD(HOUR, NUMBER, TRANS_TS) TRANS_TIME_HOUR,
        DECODE( DATEADD(HOUR, NUMBER, TRANS_TS), TIME_SLICE(TRANS_TS, 1, 'HOUR', 'START'), AMOUNT,0) AMOUNT
    FROM
        SRCTAB,
        (SELECT SEQ4() NUMBER FROM TABLE(GENERATOR(ROWCOUNT => 24)) ) G
)
GROUP BY
    TRANS_TIME_HOUR
)

【讨论】:

以上是关于在雪花中对具有不同大小的移动窗口的数字列求和的主要内容,如果未能解决你的问题,请参考以下文章

移动/调整窗口大小时闪烁

在 CTE 中对日期范围内的列求和?

在Python中对具有不同运算符的列表求和

雪花窗函数 last_value 和 max

jquery飘动的广告窗

如何添加使用 PyQt 移动窗口大小时移动的文本编辑、标签和按钮?