SQL Server:如何生成两列日期区间内的月度日期列表并拆分展示在新列中
解决SQL Server中生成日期区间月度拆分行的问题
要实现你需要的效果——把每个Case的日期区间拆分成对应月度的单独行,并生成MonthList列,用**递归CTE(公共表表达式)**是最直接的方案,正好适配SQL Server的语法。
假设你的原表名为Cases,先看最终的实现代码:
WITH DateSeries AS ( -- 锚点成员:初始化每个Case的第一个月度数据 SELECT [Case Name], DATEFROMPARTS(YEAR([StartDate]), MONTH([StartDate]), 1) AS StartDate, [EndDate], [StartDate] AS MonthList FROM Cases UNION ALL -- 递归成员:逐月生成后续的月度日期 SELECT [Case Name], DATEFROMPARTS(YEAR(MonthList), MONTH(MonthList), 1) AS StartDate, [EndDate], DATEADD(MONTH, 1, MonthList) AS MonthList FROM DateSeries -- 终止条件:生成的月度日期不超过EndDate WHERE DATEADD(MONTH, 1, MonthList) <= [EndDate] ) -- 输出最终结果,按Case和月度排序 SELECT [Case Name], StartDate, EndDate, MonthList FROM DateSeries ORDER BY [Case Name], MonthList;
代码逻辑解释:
- 锚点成员:
- 先为每个Case生成第一行数据:
StartDate被转换为对应月份的第一天(匹配你期望的输出格式),MonthList初始化为原表的StartDate。
- 先为每个Case生成第一行数据:
- 递归成员:
- 每次给当前的
MonthList加1个月,生成下一个月度的日期,同时把StartDate更新为该月度的第一天。 - 递归终止的条件是:加1个月后的
MonthList不能超过原表的EndDate,这样就不会生成超出区间的月度。
- 每次给当前的
- 最终查询:
- 从CTE中取出所有数据,按
Case Name和MonthList排序,得到你要的拆分结果。
- 从CTE中取出所有数据,按
补充说明:
如果你的原表中存在StartDate的日部分大于目标月份最大天数的情况(比如原StartDate是2021-01-31,递归生成2021-02-31时),SQL Server会自动将日期调整为目标月份的最后一天(2021-02-28),这个是系统默认的日期处理逻辑,如果你需要特殊处理可以再调整。
内容的提问来源于stack exchange,提问作者nudge
相关产品推荐
相关产品推荐

