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

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

代码说明

  1. 提取唯一Part:用SELECT DISTINCT Part FROM #test获取所有不重复的零件编号,确保每个Part只出现一次。
  2. 交叉连接日历表:将唯一Part集合和日历表交叉连接,这样每个Part只会对应一套完整的日历范围,不会重复。
  3. 左连接匹配数据:通过LEFT JOIN连接回#test表,匹配年份、月份和Part字段,用ISNULL(t.Qty, 0)将没有对应数据的月份Qty设为0,和你原来的CASE逻辑效果一致。

如果后续#test中有多个不同的Part(比如part2、part3),这个逻辑也能自动为每个Part生成独立的一套日历范围,不会出现重复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:35:11