【问题标题】:Window Function with Rolling Sum by Date按日期滚动求和的窗函数
【发布时间】:2021-01-28 04:29:04
【问题描述】:

我正在尝试编写一个查询,该查询返回过去 44 天的每一天,该天前 7 天窗口内的租金计数。

这很棘手,因为不是集合中的所有日期都是连续的,而且没有出租的日期不是数据集中的行。

这里是我下载数​​据的地方: https://www.postgresqltutorial.com/postgresql-sample-database/

我知道这需要使用 WINDOW 函数,并且很可能需要使用 ORDER BY 子句,但我的结果返回的只是一个运行总和,而不是每个日期前每 7 天的滚动总和。这是我的代码:

WITH t AS (
    SELECT date_trunc('day', rental_date) rental_date, count(rental_id) cnt
    FROM rental
    WHERE rental_date >= CURRENT_DATE - INTERVAL '44 DAYS'
    GROUP BY 1
)
SELECT rental_date, SUM(cnt) OVER w
FROM t
WINDOW w AS (ORDER BY rental_date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW)
ORDER BY rental_date DESC;

预期的输出类似于:

       Col1                            Col2                               
date_trunc1                count(rental_id) 
2006-02-21 00:00:00                     182
2006-02-20 00:00:00                     182
2006-02-19 00:00:00                     182
2006-02-18 00:00:00                     182
2006-02-17 00:00:00                     182
2006-02-16 00:00:00                     182                           
2006-02-15 00:00:00                     182
2005-08-30 00:00:00                     598
2005-08-29 00:00:00                    1224
2005-08-28 00:00:00                    1883
2005-08-27 00:00:00                    2507  
2005-08-26 00:00:00                    3135
2005-08-25 00:00:00                    3756    
2005-08-24 00:00:00                    4349
2005-08-23 00:00:00                    3374
2005-08-22 00:00:00                    3148
2005-08-21 00:00:00                    2489
2005-08-20 00:00:00                    1865
2005-08-19 00:00:00                    1237
2005-08-18 00:00:00                     616
2005-08-17 00:00:00                      23
2005-08-16 00:00:00                       0
2005-08-08 00:00:00                     671
2005-08-07 00:00:00                    1305

*数据集中不存在像“2005-08-08”和“2005-08-07”这样的奇怪的公元前日期,因为那些日子没有发生出租,但它们需要出现在输出,因为在前 7 天内确实发生在“2005-08-01”和“2005-07-30”。

【问题讨论】:

    标签: sql postgresql date window-functions


    【解决方案1】:

    我想你想要:

    SELECT r.*
    FROM (SELECT date_trunc('day', rental_date) as rental_date, COUNT(*) as day_count,
                 SUM(COUNT(*)) OVER (ORDER BY MIN(rental_date) RANGE BETWEEN INTERVAL '7 DAY' PRECEDING AND CURRENT ROW)
          FROM rental
          GROUP BY date_trunc('day', rental_date)
         ) r
    WHERE rental_date >= CURRENT_DATE - INTERVAL '44 DAY'
    ORDER BY rental_date DESC;
    

    即:

    • 窗框应该是RANGE,而不是ROWS
    • 整个时间范围的过滤应该在窗口函数之后
    • 7 天总计是前 1 天前 7 天或当前前 6 天 - 取决于当前行是否包括在内。

    【讨论】:

    • 感谢您的回复!这实际上几乎是完美的,除了我还尝试使用 date_trunc 函数按每天对结果进行分组,因为每天都会生成多个日期时间戳。
    • @strapped_gopherbro。 . .我为此调整了答案。
    • 哇,非常感谢!你不知道在过去的几天里我一直在努力解决这个问题。你是救生员!我将不得不花一些时间来真正消化它,但它就像一场梦。这太棒了!!!!!!!
    • 快速提问 - 您是如何知道在 ORDER BY 中的 rent_date 上使用 MIN() 的?
    • @strapped_gopherbro 。 . .这只是您通过聚合查询学习的一个技巧。它也适用于select 之后的order by
    猜你喜欢
    • 2021-07-21
    • 1970-01-01
    • 2021-08-13
    • 2022-01-20
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多