干得好。这应该这样做。
- 由于您始终希望 Top300 中的所有项目无论其销售数据如何,您始终必须将每个子查询的结果保留在 LEFT JOIN 的 LEFT 侧。
- 您可以将 NULL SUM 聚合解析为零
- 日期过滤器需要在 JOIN 中,因为您不想限制未加入的 Top300 项。如果将它们放在 WHERE 子句中,那么它将排除不与销售数据连接的 Top300 项目,因为这些记录的日期将为 NULL。
首先设置测试表和数据
IF OBJECT_ID('Top300', 'U') IS NOT NULL DROP TABLE Top300;
GO
IF OBJECT_ID('SalesData', 'U') IS NOT NULL DROP TABLE SalesData;
GO
CREATE TABLE Top300 (
Part varchar(10)
)
GO
CREATE TABLE SalesData (
SBITEM varchar(10)
,SBQSHP int
,SBINV int
,SBINDT int
)
GO
INSERT Top300
SELECT A.*
FROM (
SELECT * FROM Top300 WHERE 1=2
UNION ALL SELECT 'Widget1'
UNION ALL SELECT 'Widget2'
UNION ALL SELECT 'Widget3'
UNION ALL SELECT 'Widget4'
UNION ALL SELECT 'Widget5'
UNION ALL SELECT 'Widget6'
) A
INSERT SalesData
SELECT A.*
FROM (
SELECT * FROM SalesData WHERE 1=2
UNION ALL SELECT 'Widget1', 100, 1000, '20120316'
UNION ALL SELECT 'Widget2', 100, 1000, '20120316'
UNION ALL SELECT 'Widget3', 100, 1000, '20121016'
UNION ALL SELECT 'Widget4', 100, 1000, '20121016'
UNION ALL SELECT 'Widget5', 100, 1000, '20121016'
) A
现在让我们运行原始查询的更正版本
SELECT b.Part, b.Last_12_Mo, b.Last_6_Mo,
COUNT(sd.SBINV) AS Order_Count
FROM (
SELECT a.Part, a.Last_12_Mo,
ISNULL(SUM(sd.SBQSHP), 0) AS Last_6_Mo
FROM (
SELECT t3.Part, ISNULL(SUM(sd.SBQSHP),0) AS Last_12_Mo
FROM Top300 AS t3
LEFT JOIN SalesData AS sd
ON t3.Part = sd.SBITEM
AND sd.SBINDT > '20120315'
GROUP BY t3.Part
) AS a
LEFT JOIN SalesData AS sd
ON a.Part = sd.SBITEM
AND sd.SBINDT > '20121015'
GROUP BY a.Part, a.Last_12_Mo
) AS b
LEFT JOIN SalesData AS sd
ON b.Part = sd.SBITEM
AND sd.SBINDT > '20130110'
GROUP BY b.Part, b.Last_12_Mo, b.Last_6_Mo
ORDER BY b.Part
最后,让我们运行一个更简单、更优化的查询,生成相同的结果
SELECT b.Part
,SUM(CASE WHEN sd.SBINDT > '20120315' THEN sd.SBQSHP ELSE 0 END) as [Last_12_Mo]
,SUM(CASE WHEN sd.SBINDT > '20121015' THEN sd.SBQSHP ELSE 0 END) as [Last_6_Mo]
,SUM(CASE WHEN sd.SBINDT > '20130110' THEN 1 ELSE 0 END) as [Order_Count]
FROM Top300 b
LEFT JOIN SalesData AS sd
ON b.Part = sd.SBITEM
AND sd.SBINDT > '20120315'
GROUP BY b.Part
ORDER BY b.Part