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 函数来处理类似 PRECEDING
和 FOLLOWING
的限制,但是 LEAD
、LAG
类型的函数只允许您设置 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;
想法是将所有日期的日历 table 加入到您的 table 事件中,条件是月份匹配,或者前者的月份晚 1 或 2 个月。请注意,我假设每个“月”都可以用该月第一天的完整日期表示。理想情况下,您应该始终在这里使用适当的日期。
您可以分两步完成:
- 对数据进行分组(例如,A 出现了两次,但您只想计算一次,因为 A 的两行在这种情况下是相同的)
- 为下个月和下个月生成包含额外行的新数据
根据您的示例,第一步很简单,在更复杂的情况下,您可以使用 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 view
和 select event_date + 60, customer_id from view
.
否则进行适当的日期计算应该不会太难,参见Date/Time Functions and Operators。
我正在尝试创建 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 函数来处理类似 PRECEDING
和 FOLLOWING
的限制,但是 LEAD
、LAG
类型的函数只允许您设置 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;
想法是将所有日期的日历 table 加入到您的 table 事件中,条件是月份匹配,或者前者的月份晚 1 或 2 个月。请注意,我假设每个“月”都可以用该月第一天的完整日期表示。理想情况下,您应该始终在这里使用适当的日期。
您可以分两步完成:
- 对数据进行分组(例如,A 出现了两次,但您只想计算一次,因为 A 的两行在这种情况下是相同的)
- 为下个月和下个月生成包含额外行的新数据
根据您的示例,第一步很简单,在更复杂的情况下,您可以使用 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 view
和 select event_date + 60, customer_id from view
.
否则进行适当的日期计算应该不会太难,参见Date/Time Functions and Operators。