SQL Server:将数据按月份分配到日历表的正确连接方法咨询
解决SQL Server中每个Part对应唯一日历范围的连接问题
你当前的问题根源是直接使用CROSS JOIN #test——因为#test中同一个Part存在多条不同年月的记录,交叉连接会让日历表的每一行都和这些记录逐一匹配,最终同一个Part会重复出现多套完整的日历范围。
正确的做法是先提取#test中唯一的Part集合,再和日历表做交叉连接,最后通过左连接匹配对应年月的Qty值,具体实现如下:
完整修正后的测试代码
create table #test ( calYear int, calMonth int, Qty int, Part nvarchar(10) ) Insert #test values (2024, 01, 1, 'part1'), (2023, 02, 4, 'part1'), (2023, 04, 8, 'part1'), (2023, 05, 14, 'part1') CREATE TABLE #Calendar ( CalendarYear int, [CalendarMonth] int ) DECLARE @StartDate DATETIME DECLARE @EndDate DATETIME SET @EndDate = DATEADD(m,-1,GETDATE()) SET @StartDate = DATEADD(m, -11, @EndDate) WHILE @StartDate <= @EndDate BEGIN INSERT INTO #Calendar (CalendarYear, CalendarMonth) SELECT YEAR(@StartDate), MONTH(@StartDate) SET @StartDate = DATEADD(m, 1, @StartDate) END -- 核心修正查询部分 SELECT ISNULL(t.Qty, 0) AS Qty, c.CalendarYear, c.CalendarMonth, p.Part FROM #Calendar c CROSS JOIN (SELECT DISTINCT Part FROM #test) p -- 先取唯一的Part集合 LEFT JOIN #test t ON c.CalendarYear = t.calYear AND c.CalendarMonth = t.calMonth AND p.Part = t.Part DROP TABLE #Calendar DROP TABLE #test
代码说明
- 提取唯一Part:用
SELECT DISTINCT Part FROM #test获取所有不重复的零件编号,确保每个Part只出现一次。 - 交叉连接日历表:将唯一Part集合和日历表交叉连接,这样每个Part只会对应一套完整的日历范围,不会重复。
- 左连接匹配数据:通过
LEFT JOIN连接回#test表,匹配年份、月份和Part字段,用ISNULL(t.Qty, 0)将没有对应数据的月份Qty设为0,和你原来的CASE逻辑效果一致。
如果后续#test中有多个不同的Part(比如part2、part3),这个逻辑也能自动为每个Part生成独立的一套日历范围,不会出现重复。
内容的提问来源于stack exchange,提问作者siyuri0907
相关产品推荐
相关产品推荐

