2012-06-13 161 views
2

考慮下面的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 UPDATE 我修改了代碼的建議:

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行零值。但是,這些解決方案都沒有建議這樣做。

FINAL UPDATE [已解決]: Where子句阻止這些行進入最終結果集。所以,正如達爾文所說,我只是用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 
+0

其他行未顯示的原因是,通過將過濾器放在where子句(與連接相對)上,在創建數據集之後排除行。 – Dibstar

+0

嗯,我明白了。但是,我該如何解決這個問題? (順便說一句,我需要過濾這些行)。 –

+0

請參閱下面對我的版本的修改 - 應該做的竅門,如果不提供一些示例數據,我會看看哪裏出問題 – Dibstar

回答

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 
+0

@Mehdi - where子句之前錯誤排除行 - 嘗試修正版本 – Dibstar

+0

謝謝你,這個工作。但是,請您介紹一下您寫的第一個和第二個查詢版本之間的區別。我需要了解這一次,永遠:) –

+1

不同之處在於過濾器標準已經移動到連接上(x = y,a = b等的LEft外部連接順序)。之前的版本將日期加入預定義的範圍並過濾,新版本僅加入customerID,ordertype和IsvOId有效的情況。見[這裏](http://stackoverflow.com/questions/354070/sql-join-where-clause-vs-on-clause)另一個例子 – Dibstar

1

我在小提琴寫的示例代碼。 http://sqlfiddle.com/#!3/eddfe/9/0希望它有幫助。

這個想法是,你創建一個所有年份的UDF,然後做外部連接到該表。