【问题标题】:Creating Rolling Periods创建滚动期间
【发布时间】:2021-02-23 21:27:29
【问题描述】:

我希望每 6 个月创建一个滚动期,但我不确定执行此操作的最佳方式。我猜这可能必须递归完成?

我有一个包含类似于以下数据的付款表:

CREATE TABLE payments
    ([id] int, [payment_month] int, [payment_date] datetime, [payment_amount] int)
;
    
INSERT INTO payments
    ([id], [payment_month], [payment_date], [payment_amount])
VALUES
    (1, 201911, '2019-11-01 00:00:00', 50),
    (1, 201912, '2019-12-01 00:00:00', 50),
    (1, 202001, '2020-01-01 00:00:00', 50),
    (1, 202002, '2020-02-01 00:00:00', 50),
    (1, 202003, '2020-03-01 00:00:00', 50),
    (1, 202004, '2020-04-01 00:00:00', 50),
    (1, 202005, '2020-05-01 00:00:00', 50),
    (1, 202006, '2020-06-01 00:00:00', 25),
    (1, 202007, '2020-07-01 00:00:00', 50),
    (1, 202008, '2020-08-01 00:00:00', 50),
    (1, 202009, '2020-09-01 00:00:00', 15),
    (2, 201911, '2019-11-01 00:00:00', 50),
    (2, 201912, '2019-12-01 00:00:00', 50),
    (2, 202001, '2020-01-01 00:00:00', 25),
    (2, 202002, '2020-02-01 00:00:00', 50),
    (2, 202003, '2020-03-01 00:00:00', 45),
    (2, 202004, '2020-04-01 00:00:00', 45),
    (2, 202004, '2020-04-10 00:00:00', 20),
    (2, 202005, '2020-05-01 00:00:00', 25),
    (3, 202004, '2020-04-01 00:00:00', 50),
    (3, 202005, '2020-05-01 00:00:00', 50),
    (3, 202006, '2020-06-01 00:00:00', 50),
    (3, 202007, '2020-07-01 00:00:00', 50),
    (3, 202008, '2020-08-01 00:00:00', 50),
    (3, 202009, '2020-09-01 00:00:00', 300)
;

我还有一个日历表,我正在使用它返回如下数据:

CREATE TABLE calendar
    ([CalendarPeriod] int, [CalendarDate] datetime)
;
    
INSERT INTO calendar
    ([CalendarPeriod], [CalendarDate])
VALUES
    (202004, '2020-04-30 00:00:00'),
    (202005, '2020-05-31 00:00:00'),
    (202006, '2020-06-30 00:00:00'),
    (202007, '2020-07-31 00:00:00'),
    (202008, '2020-08-31 00:00:00'),
    (202009, '2020-09-30 00:00:00')
;

我希望得到一个输出,其中来自calendar 的每个CalendarPeriod 与其自身和前5个月配对。 CalendarPeriod作为报告期,每个月的滚动期为6个月。我的最终目标是通过payment_monthpayment_amounts 加入每个报告期,其中payment_month 等于报告期中的滚动月份之一。

编辑: 我预期的几个月和滚动期的产出如下表所示。如果需要,我可以操作表格以通过 CalendarPeriod 聚合。

+----------------+----------------+----------------+
| CalendarPeriod | rolling_period | rolling_amount |
+----------------+----------------+----------------+
| 202004         | 201911         | 100            |
+----------------+----------------+----------------+
| 202004         | 201912         | 100            |
+----------------+----------------+----------------+
| 202004         | 202001         | 75             |
+----------------+----------------+----------------+
| 202004         | 202002         | 100            |
+----------------+----------------+----------------+
| 202004         | 202003         | 95             |
+----------------+----------------+----------------+
| 202004         | 202004         | 165            |
+----------------+----------------+----------------+
| 202005         | 201912         | 100            |
+----------------+----------------+----------------+
| 202005         | 202001         | 75             |
+----------------+----------------+----------------+
| 202005         | 202002         | 100            |
+----------------+----------------+----------------+
| 202005         | 202003         | 95             |
+----------------+----------------+----------------+
| 202005         | 202004         | 165            |
+----------------+----------------+----------------+
| 202005         | 202005         | 125            |
+----------------+----------------+----------------+
| 202006         | 202001         | 75             |
+----------------+----------------+----------------+
| 202006         | 202002         | 100            |
+----------------+----------------+----------------+
| 202006         | 202003         | 95             |
+----------------+----------------+----------------+
| 202006         | 202004         | 165            |
+----------------+----------------+----------------+
| 202006         | 202005         | 125            |
+----------------+----------------+----------------+
| 202006         | 202006         | 75             |
+----------------+----------------+----------------+
| 202007         | 202002         | 100            |
+----------------+----------------+----------------+
| 202007         | 202003         | 95             |
+----------------+----------------+----------------+
| 202007         | 202004         | 165            |
+----------------+----------------+----------------+
| 202007         | 202005         | 125            |
+----------------+----------------+----------------+
| 202007         | 202006         | 75             |
+----------------+----------------+----------------+
| 202007         | 202007         | 100            |
+----------------+----------------+----------------+
| 202008         | 202003         | 95             |
+----------------+----------------+----------------+
| 202008         | 202004         | 165            |
+----------------+----------------+----------------+
| 202008         | 202005         | 125            |
+----------------+----------------+----------------+
| 202008         | 202006         | 75             |
+----------------+----------------+----------------+
| 202008         | 202007         | 100            |
+----------------+----------------+----------------+
| 202008         | 202008         | 100            |
+----------------+----------------+----------------+
| 202009         | 202004         | 165            |
+----------------+----------------+----------------+
| 202009         | 202005         | 125            |
+----------------+----------------+----------------+
| 202009         | 202006         | 75             |
+----------------+----------------+----------------+
| 202009         | 202007         | 100            |
+----------------+----------------+----------------+
| 202009         | 202008         | 100            |
+----------------+----------------+----------------+
| 202009         | 202009         | 315            |
+----------------+----------------+----------------+

-- Alternate:
+----------------+----------------+
| CalendarPeriod | rolling_amount |
+----------------+----------------+
| 202004         | 635            |
+----------------+----------------+
| 202005         | 660            |
+----------------+----------------+
| 202006         | 635            |
+----------------+----------------+
| 202007         | 660            |
+----------------+----------------+
| 202008         | 660            |
+----------------+----------------+
| 202009         | 880            |
+----------------+----------------+

提前感谢您的帮助。

【问题讨论】:

  • 您是否尝试过在calendarcalendar 之间使用join 来匹配6 个月的窗口?
  • 我还没有尝试过,尽管我确信会有办法做到这一点。如果我能避免这么多的连接就更好了,这是一个更大的存储过程的一部分

标签: sql sql-server datetime sum aggregate-functions


【解决方案1】:

据我了解您的问题,您希望每个时期的过去 6 个月的付款金额滚动。

我不认为你真的需要你展示的中间数据集来实现这个目标。您可以只使用窗口函数:

select c.calendarperiod,
    sum(p.payment_amount) month_amount,
    sum(sum(p.payment_amount)) over(
        order by c.calendarperiod
        rows between 5 preceding and current row
    ) rolling_6_month_amount
from calendar c
left join payments p 
    on  p.payment_date >= datefromparts(year(c.calendardate), month(c.calendardate), 1)
    and p.payment_date <  dateadd(day, 1, c.calendardate)
group by c.calendarperiod

查询从日历开始,并带上每个月对应的付款——我调整了日期间隔,以防当月最后一天有付款。然后,我们按时期汇总。最后,我们可以使用窗口函数来回顾过去 5 个时期,并对相应的付款求和。

【讨论】:

  • 这很接近,但我认为总数并不像预期的那样匹配。例如,202004 应该是 635。我想考虑在为CalendarPeriod 支付的任何滚动周期内付款。 202004 应该包含(包括)201911 和 202004 之间的付款数据 -- @GMB 更新
  • @tlk27:请edit your question 显示您想要的样本数据结果。
  • @tlk27:感谢您的编辑。问题在于日历表,它从 2020 年 4 月开始,而数据从 2019 年 11 月开始。如果您扩展日历表,那么您将获得所需的结果。看到这个 db fiddle:dbfiddle.uk/…
  • 感谢您的时间和帮助,非常感谢。我不知道rows between x preceding and current 功能
猜你喜欢
  • 2017-02-08
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
相关资源
最近更新 更多