SQL 组和按月求和 - 默认为零

发布于 2024-11-30 13:32:34 字数 1670 浏览 1 评论 0原文

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

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

I am currently grouping and summing inventory usage by month:

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)

This gives me the results that I'm expecting:

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

Question

What must I do to return zero for months where no data exsits, like this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南薇 2024-12-07 13:32:34

在过去,我通过创建一个临时表来解决这样的问题,该表将保存所需的所有日期:

    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

然后您应该有每个月的记录,无论它是否存在在库存中。

In the past, I've solved a problem like this by creating a temporary table which will hold all dates needed:

    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

Then, modify your query to join against this table:

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

Then you should have a record for each month, regardless of whether it exists in Inventory.

盗梦空间 2024-12-07 13:32:34

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

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。这样,您将始终将开始日期和结束日期之间的所有月份作为行。

You could prepare a 'calendar' table like so:

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

and then do a LEFT JOIN with your table on the month and year date parts. This way you'll always have all the months between the start and end date as rows.

泡沫很甜 2024-12-07 13:32:34

这是一种方法。这假设 @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;

Here's one way. This assumes that @StartRange and @EndRange fall within the same calendar year, otherwise you will get some funny results.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文