选择年度报告的记录(过去3年)

时间:2012-06-13 11:17:19

标签: 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.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年内生成。

第4次更新 我按照建议修改了代码:

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行ZERO值。但是,这些解决方案都没有提到这一点。

最终更新[求助]: 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

2 个答案:

答案 0 :(得分:1)

我在小提琴中编写了示例代码。 http://sqlfiddle.com/#!3/eddfe/9/0希望它有所帮助。

这个想法是你创建了一个包含所有年份的UDF,然后对该表进行外连接。

答案 1 :(得分:0)

以下内容如何:

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