SQL 将所有事件放入 3 个月的桶中

SQL bin all events into 3 month buckets

我正在尝试创建 3 个月的前瞻类型 table。因此,例如 LAST_DAY(event_date) = '2021-01-01'(即 2021 年 1 月)的任何事件都将在 2021 年 2 月和 2021 年 3 月有效。

对于每个事件,我想要在事件发生后的 2 个月内再排一行。下面的示例:

给出的数据如下所示:

event_date customer_id
Jan-21 A
Feb-21 B
Jan-21 A
Jun-21 C
Mar-21 D

我想创建一些看起来像这样的东西:

event_date customer_id
Jan-21 A
Feb-21 A
Mar-21 A
Feb-21 B
Mar-21 B
Apr-21 B
Jun-21 C
Jul-21 C
Aug-21 C
Mar-21 D
Apr-21 D
May-21 D

有点卡在如何实现这个问题上。您可以假设 event_date 是此处的有效日期时间字段。我尝试了几种不同的方法但无济于事。我通常会使用 window 函数来处理类似 PRECEDINGFOLLOWING 的限制,但是 LEADLAG 类型的函数只允许您设置 1 个偏移量而不是偏移范围。

感谢任何帮助。在 PSQL 中工作。

我们可以在这里使用日历 table 方法:

WITH months AS (
    SELECT date_trunc('day', dd)::date AS month
    FROM generate_series ('2021-01-01'::timestamp,
                          '2021-12-01'::timestamp,
                          '1 month'::interval) dd
)

SELECT DISTINCT m.month, t.customer_id
FROM months m
INNER JOIN yourTable t
    ON m.month BETWEEN t.event_date AND t.event_date + interval '2 month'
ORDER BY
    t.customer_id, m.month;

Demo

想法是将所有日期的日历 table 加入到您的 table 事件中,条件是月份匹配,或者前者的月份晚 1 或 2 个月。请注意,我假设每个“月”都可以用该月第一天的完整日期表示。理想情况下,您应该始终在这里使用适当的日期。

您可以分两步完成:

  1. 对数据进行分组(例如,A 出现了两次,但您只想计算一次,因为 A 的两行在这种情况下是相同的)
  2. 为下个月和下个月生成包含额外行的新数据

根据您的示例,第一步很简单,在更复杂的情况下,您可以使用 group by 对数据进行分组,这里 distinct 就足够了:

select distinct event_date, customer_id from table;

这是基础,每行生成的其他两个信息都依赖于此数据。也许您可以为此创建一个视图并重用它。我将这样做并将其命名为 view,但您也可以直接使用 SQL 语句。将其视为 view 等于 select distinct event_date, customer_id from table.

第二步可以通过添加下个月的数据来完成,类似地添加下个月的数据。想到工会。

select event_date, customer_id from view
UNION 
select next_month(event_date), customer_id from view
UNION
select after_next_month(event_date), customer_id from view

现在只剩下日期运算了,你要计算下一个月和下一个月

如果这对你来说没问题,我建议你只在日期上加上 30,例如select event_date + 30, customer_id from viewselect event_date + 60, customer_id from view.

否则进行适当的日期计算应该不会太难,参见Date/Time Functions and Operators