如何按季度拆分给定日期范围并修正SQL CTE起始错误?
实际数据
| ID | StartDateTime | EndDateTime | Price |
|---|---|---|---|
| 1 | 2024-01-01 | 2024-06-30 | 14.00 |
| 2 | 2024-07-01 | 2024-12-30 | 10.00 |
期望输出
| ID | StartDateTime | EndDateTime | Price |
|---|---|---|---|
| 1 | 2024-01-01 | 2024-03-31 | 14.00 |
| 1 | 2024-04-01 | 2024-06-30 | 14.00 |
| 2 | 2024-07-01 | 2024-09-30 | 10.00 |
| 2 | 2024-10-01 | 2024-12-30 | 10.00 |
我尝试了以下SQL CTE代码,但该代码会从第二季度开始,无法得到正确结果,请问如何根据给定日期范围拆分出所有季度的起止日期?
with cte as ( select id, start_date, num_quarters from t union all select id, dateadd(month, 3, start_date), num_quarters - 1 from cte where num_quarters > 1 ) select * from cte;
你的原代码只生成了季度起始日期,没有对应计算每个季度的结束日期,也未处理与原记录结束日期的截断逻辑,导致结果缺失完整的季度区间。以下是修正后的递归CTE方案(基于SQL Server语法):
WITH QuarterlySplits AS ( -- 初始化:从原记录的起始日期开始,计算第一个季度的结束日期 SELECT ID, StartDateTime AS CurrentStart, -- 计算当前季度的自然结束日:先定位到季度初,再加3个月减1天 DATEADD(DAY, -1, DATEADD(MONTH, ((DATEPART(QUARTER, StartDateTime)-1)*3)+3, DATEFROMPARTS(YEAR(StartDateTime), 1, 1))) AS CurrentEnd, EndDateTime AS OriginalEnd, Price FROM t UNION ALL -- 递归生成后续季度 SELECT ID, DATEADD(DAY, 1, CurrentEnd) AS CurrentStart, -- 计算下一个季度的结束日,若超过原记录的结束日期则截断 CASE WHEN DATEADD(QUARTER, 1, CurrentEnd) > OriginalEnd THEN OriginalEnd ELSE DATEADD(DAY, -1, DATEADD(MONTH, 3, DATEADD(DAY, 1, CurrentStart))) END AS CurrentEnd, OriginalEnd, Price FROM QuarterlySplits -- 只要当前季度结束日还小于原记录结束日,就继续递归 WHERE CurrentEnd < OriginalEnd ) SELECT ID, CurrentStart AS StartDateTime, CurrentEnd AS EndDateTime, Price FROM QuarterlySplits ORDER BY ID, StartDateTime;
这个方案的逻辑是:
- 先为每条原记录生成第一个季度的完整区间,确保起始日与原记录一致,结束日为该季度的自然月末
- 通过递归生成后续季度的起始日(上一季度结束日+1),并计算对应季度的结束日,若该自然季度末超过原记录的结束日期,则直接用原记录的结束日期作为该条的结束日
- 直到所有季度区间都覆盖原记录的日期范围为止
内容的提问来源于stack exchange,提问作者Nithin
相关产品推荐
相关产品推荐

