Sql server 为年度报告选择记录(过去3年)
考虑以下SQL语句:Sql server 为年度报告选择记录(过去3年),sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,考虑以下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.Or
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年的订单,我需要生成另外两行(尽管值为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)
这将生成一个结果集,如下所示(我已对此进行了检查,并确保情况属实)
然后我按如下方式连接表(右连接):
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
那么以下内容如何:
DECLARE @CustomerId INT = 48;
DECLARE @CurrentYear INT = DATEPART(YEAR, GETDATE());
;with years as
(
SELECT YEAR(GETDATE()) as yr
UNION ALL SELECT YEAR(DATEADD(YY,-1,GETDATE()))
UNION ALL SELECT YEAR(DATEADD(YY,-2,GETDATE()))
)
SELECT
years.yr
,0 AS Month
,SUM(ISNULL(o.GrandTotal,0)) AS GrandTotal
FROM years
LEFT OUTER JOIN Order o
ON YEAR(o.OrderDate) = years.yr
AND o.customerid = @customerid
AND o.OrderTypeId = 4
AND o.IsVoid = 0
GROUP BY
years.yr
我用fiddle编写了示例代码。希望能有帮助
我们的想法是,您创建一个包含所有年份的UDF,然后对该表进行外部联接。@Mehdi-where子句之前错误地排除了行-尝试修改版本谢谢,这一个有效。但是,请您描述一下您编写的查询的第一个版本和第二个版本之间有什么区别?我需要一劳永逸地理解这一点:)区别在于过滤条件已被移动到联接上(左外部联接顺序为x=y,a=b等)。以前的版本将日期加入到预定义的范围中,然后进行过滤,新版本仅加入customerID、ordertype和IsvOId有效的情况。请参见另一个示例其他行没有显示的原因是,通过在where子句上放置筛选器(与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) AND
o.CustomerId = @CustomerId AND
o.OrderTypeId = 4 AND
o.IsVoid = 0
GROUP BY
y.yr
DECLARE @CustomerId INT = 48;
DECLARE @CurrentYear INT = DATEPART(YEAR, GETDATE());
;with years as
(
SELECT YEAR(GETDATE()) as yr
UNION ALL SELECT YEAR(DATEADD(YY,-1,GETDATE()))
UNION ALL SELECT YEAR(DATEADD(YY,-2,GETDATE()))
)
SELECT
years.yr
,0 AS Month
,SUM(ISNULL(o.GrandTotal,0)) AS GrandTotal
FROM years
LEFT OUTER JOIN Order o
ON YEAR(o.OrderDate) = years.yr
AND o.customerid = @customerid
AND o.OrderTypeId = 4
AND o.IsVoid = 0
GROUP BY
years.yr