[英]SQL Group and Sum By Month - Default to Zero
我目前正在按月對庫存使用情況進行分組和匯總:
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
過去,我通過創建一個臨時表來解決這樣的問題,該表將保存所有需要的日期:
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
然后,無論庫存中是否存在該記錄,您都應該有每個月的記錄。
您可以像這樣准備一個“日歷”表:
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
。 這樣,您始終可以將開始日期和結束日期之間的所有月份都作為行。
這是一種方法。 假設@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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.