You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL技术问询:如何调整CTE语句以生成指定日期范围内的完整月份区间表

解决SQL日期区间按月拆分的问题

你的核心问题在于递归生成下一个月的起始日期时,没有重置为当月的第一天,而是直接在上个月的起始日期上加了一个月,导致后续月份的StartDate不是当月1号,同时终止条件也需要调整来包含最后一个不完整的月份。

修正后的SQL语句

DECLARE @start DATE = '2011-05-21'
DECLARE @end DATE = '2011-08-17';

WITH months (StartDate, EndDate) AS (
    -- 初始行:第一个月的起始是给定的@start,结束是当月月末(如果月末超过@end则取@end)
    SELECT 
        @start,
        IIF(EOMONTH(@start) > @end, @end, EOMONTH(@start))
    UNION ALL
    -- 递归生成后续月份:起始为下一个月的第一天,结束为当月月末或@end(取较小值)
    SELECT 
        DATEADD(month, DATEDIFF(month, 0, StartDate) + 1, 0), -- 获取下一个月的第一天
        IIF(EOMONTH(DATEADD(month, DATEDIFF(month, 0, StartDate) + 1, 0)) > @end, @end, EOMONTH(DATEADD(month, DATEDIFF(month, 0, StartDate) + 1, 0)))
    FROM months
    -- 终止条件:下一个月的第一天 <= @end,确保最后一个不完整的月份被包含
    WHERE DATEADD(month, DATEDIFF(month, 0, StartDate) + 1, 0) <= @end
)
SELECT StartDate, EndDate FROM months;

关键调整点

  • 递归的起始日期修正:用DATEADD(month, DATEDIFF(month, 0, StartDate) + 1, 0)来获取下一个月的第一天,而不是直接在上个月的StartDate上加一个月,这样保证每个后续月份的StartDate都是当月1号。
  • 终止条件优化:判断下一个月的第一天是否小于等于@end,这样能正确触发最后一个月份的生成(哪怕这个月份不完整)。
  • EndDate的边界处理:用IIF函数判断当月月末是否超过@end,如果超过就取@end作为该月的结束日期,确保最后一个月的结束是给定的@end。

测试结果

执行上述语句后,会得到你期望的输出:

StartDate   EndDate
----------  ----------
2011-05-21  2011-05-31
2011-06-01  2011-06-30
2011-07-01  2011-07-31
2011-08-01  2011-08-17

内容的提问来源于stack exchange,提问作者Sandeep Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 17:47:37