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

SQL Server 2008 R2从指定日期生成跨年度逐月行记录问题

解决方案

你的原有查询问题在于仅对月份做累加,未处理月份到12后年份自动进位的逻辑,且终止条件仅判断月份未考虑年份差,因此无法生成跨年度的月份数据。
可以通过直接递增加月份的方式实现需求,SQL Server的DATEADD函数会自动处理年月的进位逻辑,无需手动判断边界,适配SQL Server 2008 R2版本的查询如下:

;WITH listOfMonth(CurrentMonth, ContractId)
AS
(
    SELECT 
       -- 取InsertDate所在月的第一天,避免日期天数影响后续计算
       DATEADD(MONTH, DATEDIFF(MONTH, 0, InsertDate), 0) AS CurrentMonth,
       Id AS ContractId 
    FROM tblContract  
    WHERE Id = 6674
    UNION ALL
    SELECT 
       DATEADD(MONTH, 1, CurrentMonth) AS CurrentMonth,
       ContractId
    FROM listOfMonth
    -- 终止条件:当前递归的月份小于当前系统时间的月份
    WHERE DATEADD(MONTH, 1, CurrentMonth) < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
)
SELECT 
    ROW_NUMBER() OVER(ORDER BY CurrentMonth) AS ID,
    DATEPART(MONTH, CurrentMonth) AS MonthNumber,
    ContractId,
    DATEPART(YEAR, CurrentMonth) AS YearNumber
FROM listOfMonth
-- 如果年月跨度超过100个月,需要取消递归深度限制,加上下面这行
-- OPTION (MAXRECURSION 0)

逻辑说明

  • 锚点查询直接取InsertDate所在月份的第一天作为递归起始值,避免当月日期天数(比如4月30日)对后续月份加减的影响
  • 每次递归直接对日期加1个月,自动处理12月之后跳转到下一年1月的逻辑
  • 终止条件判断下个月是否早于当前系统时间的当月第一天,确保生成的月份到当前月为止
  • 最终查询通过ROW_NUMBER()生成自增ID,从日期中提取年份和月份即可得到你需要的输出格式

注意事项

  1. 如果你原表中的起始日期字段是StartDate而非提问中说明的InsertDate,自行替换锚点查询中的字段名即可
  2. 原有代码中ContracId拼写缺失字母t,修正为标准的ContractId避免后续关联出错
  3. 如果需要生成的年月跨度超过100个月,需要取消注释最后一行的OPTION (MAXRECURSION 0)解除递归深度限制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:36:03