【问题标题】:How can I partition by group that falls within a time range?如何按时间范围内的组进行分区?
【发布时间】:2021-12-22 01:33:12
【问题描述】:

我有下表显示客户购买某种产品的时间。我的数据是CustomerID, Amount, Dat。我正在尝试创建列ProductsIn30Days,它表示客户在Dat-30 天(包括当天)范围内购买了多少产品。

例如,ProductsIn30Days for CustomerID 1 on Dat 25.3.2020 是 7,因为客户在 2020 年 3 月 25 日购买了 2 件产品,在 2020 年 3 月 24 日又购买了 5 件产品,这在 25.3 之前的 30 天内.2020.

CustomerID Amount Dat ProductsIn30Days
1 1 23.3.2018 1
1 2 24.3.2020 2
1 3 24.3.2020 5
1 2 25.3.2020 7
1 2 24.5.2020 2
1 1 15.6.2020 3
2 7 24.3.2017 7
2 2 24.3.2020 2

我尝试过这样的事情但没有成功,因为分区只能在单个日期上工作,而不是在我需要的范围内:

select CustomerID, Amount, Dat,
sum(Amount) over (partition by CustomerID, Dat-30)
from table

感谢您的帮助。

【问题讨论】:

    标签: sql oracle date range


    【解决方案1】:

    您可以使用带有范围窗口的解析 SUM 函数:

    SELECT t.*,
           SUM(Amount) OVER (
             PARTITION BY CustomerID
             ORDER BY Dat
             RANGE BETWEEN INTERVAL '30' DAY PRECEDING AND CURRENT ROW
           ) AS ProductsIn30Days
    FROM   table_name t;
    

    其中,对于样本数据:

    CREATE TABLE table_name (CustomerID, Amount, Dat) AS
    SELECT 1, 1, DATE '2018-03-23' FROM DUAL UNION ALL
    SELECT 1, 2, DATE '2020-03-24' FROM DUAL UNION ALL
    SELECT 1, 3, DATE '2020-03-24' FROM DUAL UNION ALL
    SELECT 1, 2, DATE '2020-03-25' FROM DUAL UNION ALL
    SELECT 1, 2, DATE '2020-05-24' FROM DUAL UNION ALL
    SELECT 1, 1, DATE '2020-06-15' FROM DUAL UNION ALL
    SELECT 2, 7, DATE '2017-03-24' FROM DUAL UNION ALL
    SELECT 2, 2, DATE '2020-03-24' FROM DUAL;
    

    输出:

    CUSTOMERID AMOUNT DAT PRODUCTSIN30DAYS
    1 1 2018-03-23 00:00:00 1
    1 2 2020-03-24 00:00:00 5
    1 3 2020-03-24 00:00:00 5
    1 2 2020-03-25 00:00:00 7
    1 2 2020-05-24 00:00:00 2
    1 1 2020-06-15 00:00:00 3
    2 7 2017-03-24 00:00:00 7
    2 2 2020-03-24 00:00:00 2

    注意:如果您在同一日期有值,那么它们将按顺序绑定并始终聚合在一起(即第 2 行和第 3 行)。如果您希望将它们单独聚合,那么您需要通过其他方式订购以打破联系,但这不适用于RANGE 窗口。

    db小提琴here

    【讨论】:

    • 谢谢,这很好用!当我尝试使用更大的间隔(200 天)时,出现错误 01873. 00000 - “间隔的前导精度太小”。我可以通过将 INTERVAL '200' DAY 更改为 INTERVAL '200' DAY(3) 来解决这个问题。
    • @Dudelstein 是的,这是解决该领先精度问题的正确语法。
    猜你喜欢
    • 1970-01-01
    • 2014-07-23
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    相关资源
    最近更新 更多