SQL Server 2014存储过程跨年度数据返回异常求助
问题分析与解决方案
你的问题出在循环中对@StartMonth的更新逻辑上:当月份超过12时,你只递增了@StartYear,但没有将@StartMonth重置为1。这会导致跨年后,@StartMonth的值会变成13、14……直到超出@EndMonth,循环提前终止,无法生成2018年的月份列。
另外,你的代码里两次重复查询tbl_Consumption,这会降低查询性能,建议用ISNULL或COALESCE来简化逻辑,避免重复子查询。
修正后的代码
DECLARE @StartPeriod DATETIME = N'01/01/2017 00:00:00', @EndPeriod DATETIME = N'12/30/2018 00:00:00' DECLARE @query VARCHAR(MAX) = '', -- 初始化@query为空字符串,避免初始值为NULL @StartMonth int = MONTH(@StartPeriod), @EndMonth int = MONTH(@EndPeriod), @StartYear int = YEAR(@StartPeriod), @EndYear int = YEAR(@EndPeriod), @Period datetime = @StartPeriod WHILE (@StartYear < @EndYear OR (@StartYear = @EndYear AND @StartMonth <= @EndMonth)) BEGIN -- 用ISNULL简化子查询,避免重复查询 SET @query = @query + ' ISNULL((SELECT Consumption FROM tbl_Consumption c WHERE c.ProductID = a.ProductID AND YEAR(c.StartPeriod) = ' + CONVERT(VARCHAR, YEAR(@Period)) + ' AND MONTH(c.StartPeriod) = ' + CONVERT(VARCHAR, MONTH(@Period)) + '), 0.00) AS [Usage (' + LEFT(DATENAME(MONTH, @Period),3) + ' ' + CONVERT(VARCHAR, YEAR(@Period)) + ')],' SET @Period = DATEADD(MONTH, 1, @Period) SET @StartMonth = @StartMonth + 1 -- 当月份超过12时,重置月份为1并递增年份 IF @StartMonth > 12 BEGIN SET @StartYear = @StartYear + 1 SET @StartMonth = 1 -- 关键:重置月份为1 END END
关键修改点说明
- 重置@StartMonth为1:在年份递增时,必须把月份重置为1,这样下一轮循环的月份判断才会从1月开始,确保跨年后的所有月份都能被处理。
- 初始化@query为空字符串:避免
@query初始为NULL导致拼接后结果始终为NULL。 - 简化子查询:用
ISNULL包裹子查询,只执行一次消费数据查询,提升性能的同时让代码更简洁。 - 直接使用YEAR()和MONTH()函数:无需将
@Period转为字符串再去解析日期,直接提取年份和月份更高效且避免格式问题。
这样修改后,循环就能正确遍历从2017年1月到2018年12月的所有月份,生成完整的动态列。
内容的提问来源于stack exchange,提问作者Arian Caen Holt
相关产品推荐
相关产品推荐

