Consider the following SQL statement:
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)
which correctly produces the result:
2012, 0, 89.00
2011, 0, 230.00
2010, 0, 450.0
However, if another customer has placed an order just for year 2011, I need to have those 2 other rows generated (albeit with 0 values):
2011, 0, 230.00
2012, 0, 0
2010, 0, 0
How am I suppose to do this correctly? Please note that the report is going to be generated for the last 3 years.
4th UPDATE I modified the code as suggested:
DECLARE @CustomerId INT = 48;
DECLARE @CurrentYear INT = YEAR(GETDATE());
DECLARE @years TABLE (
yr INT
);
INSERT INTO @years VALUES
(@CurrentYear),
(@CurrentYear - 1),
(@CurrentYear - 2)
This produces a result set as follows (I've checked that and made sure that this is the case).
2012
2011
2010
Then I join the tables (RIGHT JOIN) as follows:
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
But, consider that the customer hasn't placed an order yet, so, this needs to produce 3 rows with ZERO values. However, none of those solutions suggested does this.
FINAL UPDATE [SOLVED]: The where clause prevented those rows from being in the final result set. So, as Darvin suggested, I just replaced the WHERE clause with AND and the problem is gone.
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