【发布时间】:2012-06-16 08:13:25
【问题描述】:
考虑以下 SQL 语句:
DECLARE @CustomerId INT = 48;
DECLARE @CurrentYear INT = DATEPART(YEAR, GETDATE());
SELECT
YEAR(o.OrderDate) AS Year,
0 AS Month,
SUM(o.GrandTotal) AS GrandTotal
FROM [Order] o
WHERE
o.CustomerId = @CustomerId AND
o.OrderTypeId = 4 AND
o.IsVoid = 0 AND
YEAR(o.OrderDate) BETWEEN @CurrentYear - 2 AND @CurrentYear
GROUP BY
YEAR(o.OrderDate)
正确地产生结果:
2012, 0, 89.00
2011, 0, 230.00
2010, 0, 450.0
但是,如果另一个客户仅在 2011 年下订单,我需要生成另外 2 行(尽管值为 0):
2011, 0, 230.00
2012, 0, 0
2010, 0, 0
我应该如何正确地做到这一点?请注意,将生成过去 3 年的报告。
第四次更新 我按照建议修改了代码:
DECLARE @CustomerId INT = 48;
DECLARE @CurrentYear INT = YEAR(GETDATE());
DECLARE @years TABLE (
yr INT
);
INSERT INTO @years VALUES
(@CurrentYear),
(@CurrentYear - 1),
(@CurrentYear - 2)
这会产生如下结果集(我已经检查过并确保是这种情况)。
2012
2011
2010
然后我加入表格(RIGHT JOIN)如下:
SELECT
y.yr AS Year,
0 AS Month,
SUM(ISNULL(o.GrandTotal, 0)) AS GrandTotal
FROM [Order] o
RIGHT JOIN @years y ON y.yr = YEAR(o.OrderDate)
WHERE
o.CustomerId = @CustomerId AND
o.OrderTypeId = 4 AND
o.IsVoid = 0
GROUP BY
y.yr
但是,考虑到客户还没有下订单,所以,这需要产生 3 行的零值。但是,建议的这些解决方案都没有做到这一点。
最终更新 [已解决]: where 子句阻止这些行出现在最终结果集中。所以,正如 Darvin 所建议的,我只是用 AND 替换了 WHERE 子句,问题就消失了。
SELECT
y.yr AS Year,
0 AS Month,
SUM(ISNULL(o.GrandTotal, 0)) AS GrandTotal
FROM [Order] o
RIGHT JOIN @years y ON y.yr = YEAR(o.OrderDate) AND
o.CustomerId = @CustomerId AND
o.OrderTypeId = 4 AND
o.IsVoid = 0
GROUP BY
y.yr
【问题讨论】:
-
其他行没有显示的原因是通过将过滤器放在 where 子句上(与连接相反),在创建数据集后将排除行。
-
好吧,我想通了。但是,我应该如何解决这个问题? (顺便说一下,我需要过滤这些行)。
-
请参阅下面对我的版本的修改 - 如果不提供一些示例数据,我会看看哪里出错了
标签: sql-server sql-server-2008 tsql