如何将用户订阅起止日期表转换为按日维度的日历结构表?
将订阅起止日期表转换为每日订阅记录表
原表结构及数据
| 用户 | 产品 | 起始日期 | 结束日期 |
|---|---|---|---|
| A | trial | 2022-01-30 | 2022-03-01 |
| A | paid | 2022-03-02 | 2023-03-02 |
| A | trial | 2023-03-03 | 2023-04-02 |
| B | trial | 2022-05-06 | 2022-06-05 |
| B | trial | 2022-06-06 | 2022-07-06 |
| B | paid | 2022-07-07 | 2023-07-07 |
| C | trial | 2022-11-21 | 2022-12-21 |
| C | paid | 2022-12-22 | 2023-12-22 |
| C | paid | 2023-12-23 | 2024-12-22 |
目标表结构
需要生成按日期展示每个用户当日订阅产品的表,示例如下:
| 日期 | 用户 | 产品 |
|---|---|---|
| 2022-01-30 | A | trial |
| 2022-01-31 | A | trial |
| ... | ... | ... |
| 2022-03-02 | A | paid |
原SQL的问题
你提供的SQL存在两处语法错误:
- 子查询
q缺少SELECT关键字,正确写法需明确指定查询字段 SELECT语句末尾多了一个冗余逗号,会导致语法报错
另外,固定生成2018-2030的日期数组会包含大量不需要的日期,建议根据原表的实际起止日期动态生成,提升查询效率。
修正后的SQL代码
WITH dates AS ( SELECT date FROM UNNEST(GENERATE_DATE_ARRAY( (SELECT MIN(start_date) FROM table1), (SELECT MAX(end_date) FROM table1), INTERVAL 1 DAY )) AS date ) SELECT b.date, q.user, q.product FROM ( SELECT user, product, start_date, end_date FROM table1 ) q CROSS JOIN dates b WHERE b.date BETWEEN q.start_date AND q.end_date ORDER BY b.date, q.user
说明
- 动态日期范围:通过原表的最小起始日期和最大结束日期生成必要的日期数组,避免无效数据占用资源
- 语法修正:补全子查询的
SELECT关键字,删除冗余逗号 - 结果排序:增加
ORDER BY按日期和用户排序,让输出结果更贴合目标格式
内容的提问来源于stack exchange,提问作者user2458552
相关产品推荐
相关产品推荐

