【问题标题】:SQL Group and Sum By Month - Default to ZeroSQL 分组和按月求和 - 默认为零
【发布时间】:2023-03-09 21:57:01
【问题描述】:

我目前正在按月对库存使用情况进行分组和汇总:

SELECT      Inventory.itemid AS ItemID,
            SUM(Inventory.Totalunits) AS Individual_MonthQty,
            MONTH(Inventory.dadded) AS Individual_MonthAsNumber,
            DATENAME(MONTH, Inventory.dadded) AS Individual_MonthAsString
FROM        Inventory
WHERE       Inventory.invtype = 'Shipment'
AND         Inventory.dadded >= @StartRange
AND         Inventory.dadded <= @EndRange
GROUP BY    Inventory.ItemID, 
            MONTH(Inventory.dadded), 
            DATENAME(MONTH, Inventory.dadded)

这给了我预期的结果:

ItemID  Kit_MonthQty    Kit_MonthAsNumber   Kit_MonthAsString
13188   234             8                   August
13188   45              9                   September
13188   61              10                  October
13188   20              12                  December

问题

我必须做些什么才能在没有数据存在的月份返回 ,如下所示:

ItemID  Kit_MonthQty    Kit_MonthAsNumber   Kit_MonthAsString
13188   0               1                   January
13188   0               2                   February
13188   0               3                   March
13188   0               4                   April
13188   0               5                   May
13188   0               6                   June
13188   0               7                   July
13188   234             8                   August
13188   45              9                   September
13188   61              10                  October
13188   0               11                  November
13188   20              12                  December

【问题讨论】:

标签: sql sql-server-2005 group-by


【解决方案1】:

过去,我通过创建一个包含所有所需日期的临时表来解决这样的问题:

    CREATE TABLE #AllDates (ThisDate datetime null)
    SET @CurrentDate = @StartRange

    -- insert all dates into temp table
    WHILE @CurrentDate <=  @EndRange
        BEGIN
            INSERT INTO #AllDates values(@CurrentDate)
            SET @CurrentDate = dateadd(mm, 1, @CurrentDate)
        END

然后,修改您的查询以加入此表:

SELECT      ALLItems.ItemId,
            SUM(COALESCE(Inventory.Qty, 0)) AS Individual_MonthQty,
            MONTH(#AllDates.ThisDate) AS Individual_MonthAsNumber,
            DATENAME(MONTH, #AllDates.ThisDate) AS Individual_MonthAsString
FROM        #AllDates
            JOIN (SELECT DISTINCT dbo.Inventory.ItemId FROM dbo.Inventory)  AS ALLItems ON 1 = 1
            LEFT JOIN Inventory ON DATEADD(dd, - DAY(Inventory.dadded) +1, Inventory.dadded) = #AllDates.ThisDate AND ALLItems.ItemId = dbo.Inventory.ItemId
WHERE       
            #AllDates.ThisDate >= @StartRange
AND         #AllDates.ThisDate <= @EndRange
GROUP BY    ALLItems.ItemId, 
            #AllDates.ThisDate

那么你应该有每个月的记录,不管它是否存在于 Inventory 中。

【讨论】:

  • 你也需要按年加入
  • 是的,你是正确的 Cyber​​Dude。我想说我故意把它作为一个练习留给原始海报来解决,但我会撒谎:)
  • @PaulStock,我知道你要去哪里,但我无法到达那里。即使使用左连接,Inventory.ItemID 将如何与不包含数据的月份相关联?
  • @James Hill - 你是对的。我已经更正了代码并添加了一行来获取所有库存项目。
  • @PaulStock,感谢您的更新!不幸的是,当我在加入时添加年份时,我又回到了只有几个月的数据记录。我发现问题在于这个标准:AND Inventory.invtype = 'Kit Assembly'。如果我删除它,我每个月都有记录,即使它们为零。有什么想法吗?
【解决方案2】:

您可以像这样准备一个“日历”表:

DECLARE @d datetime
SET @d = @StartRange

DECLARE @calendar TABLE (Date datetime)

WHILE (@d <= @EndRange) BEGIN
    INSERT INTO @Calendar VALUES (@d)
    SET @d = DATEADD(month, 1, @d)
END

然后在月份和年份日期部分对您的表格执行LEFT JOIN。这样,您将始终将开始日期和结束日期之间的所有月份作为行。

【讨论】:

    【解决方案3】:

    这是一种方法。这假设@StartRange@EndRange 属于同一日历年,否则你会得到一些有趣的结果。

    WITH n(n) AS 
    (
        SELECT TOP 12 ROW_NUMBER() OVER (ORDER BY [object_id])
            FROM sys.objects
    ),
    months(m, mn) AS
    (
        SELECT n, DATENAME(MONTH, DATEADD(MONTH, m-1, '19000101')) 
            FROM n
    )
    SELECT 
        ItemID = i.itemid,
        MonthQty = COALESCE(SUM(TotalUnits), 0),
        MonthAsNumber = m.m,
        MonthAsString = m.mn
    FROM
        months AS m
    LEFT OUTER JOIN
        Inventory AS i
    ON
        MONTH(i.dadded) = m.m
    WHERE
        i.invtype = 'Shipment'
        AND i.dadded >= @StartRange
        AND i.dadded <= @EndRange
    GROUP BY
        m.m, m.mn, i.itemid
    ORDER BY m.m;
    

    【讨论】:

      猜你喜欢
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多