2015-01-08 14 views
8

我知道你們中許多人觀察到了這種行爲,但我想知道是否有人可以解釋原因。當我創建一個小的表創建使用旋轉功能的一個例子,我得到的結果,我期望:爲什麼使用「額外」列進行轉角不能結合結果

CREATE TABLE dbo.AverageFishLength 
    (
     Fishtype VARCHAR(50) , 
     AvgLength DECIMAL(8, 2) , 
     FishAge_Years INT 
    ) 
INSERT INTO dbo.AverageFishLength 
     (Fishtype, AvgLength, FishAge_Years) 
VALUES ('Muskie', 32.75, 3), 
     ('Muskie', 37.5, 4), 
     ('Muskie', 39.75, 5), 
     ('Walleye', 16.5, 3), 
     ('Walleye', 18.25, 4), 
     ('Walleye', 20.0, 5), 
     ('Northern Pike', 20.75, 3), 
     ('Northern Pike', 23.25, 4), 
     ('Northern Pike', 26.0, 5); 

這裏是樞軸查詢:

SELECT Fishtype , 
     [3] AS [3 Years Old] , 
     [4] AS [4 Years Old] , 
     [5] AS [5 Years Old] 
FROM dbo.AverageFishLength PIVOT(SUM(AvgLength) 
           FOR FishAge_Years IN ([3], [4], [5])) AS PivotTbl 

下面是結果:

enter image description here

但是,如果我創建一個帶有標識列的表,結果走散被分成幾行:

DROP TABLE dbo.AverageFishLength 
CREATE TABLE dbo.AverageFishLength 
    (
     ID INT IDENTITY(1,1) , 
     Fishtype VARCHAR(50) , 
     AvgLength DECIMAL(8, 2) , 
     FishAge_Years INT 
    ) 
INSERT INTO dbo.AverageFishLength 
     (Fishtype, AvgLength, FishAge_Years) 
VALUES ('Muskie', 32.75, 3), 
     ('Muskie', 37.5, 4), 
     ('Muskie', 39.75, 5), 
     ('Walleye', 16.5, 3), 
     ('Walleye', 18.25, 4), 
     ('Walleye', 20.0, 5), 
     ('Northern Pike', 20.75, 3), 
     ('Northern Pike', 23.25, 4), 
     ('Northern Pike', 26.0, 5); 

完全相同的查詢:

SELECT Fishtype , 
     [3] AS [3 Years Old] , 
     [4] AS [4 Years Old] , 
     [5] AS [5 Years Old] 
FROM dbo.AverageFishLength PIVOT(SUM(AvgLength) 
           FOR FishAge_Years IN ([3], [4], [5])) AS PivotTbl 

不同的結果:

enter image description here

在我看來,該ID列在查詢中被使用,即使它不出現在查詢中。它幾乎就像它隱式地包含在查詢中,但沒有顯示在結果集中。

任何人都可以解釋爲什麼發生這種情況?

+1

我應該補充一點,我知道如何解決它,使用子查詢或row_number結束......我真的只是對它發生的原因感興趣。 –

+2

這個問題讓我餓了 – billinkc

回答

11

發生這種情況的原因在於ID列對於每一行都是唯一的,並且由於您直接查詢表(不包含子查詢),因此該列作爲GROUP BY聚合函數所需的一部分包含在內。

該文檔的MSDN docs about FROM狀態如下:

table_source PIVOT <pivot_clause>

指定table_source是基於pivot_column中的擺動。 table_source是一個表或表的表達式。輸出是一個表,其中包含除了pivot_column和value_column之外的table_source的所有列。除了pivot_column和value_column之外,table_source的列被稱爲數據透視操作符的分組列

PIVOT對輸入表分組操作相對於分組列並返回一行每個組。此外,輸出包含column_list中指定的每個值的一列,該列顯示在input_table的pivot_column中。

你的版本基本上是說SELECT * FROM yourtable和PIVOT那個數據。即使ID列不在最終的SELECT列表中,它也是查詢中的一個分組元素。如果您將PIVOT與「pre-PIVOT」示例進行比較以顯示您將看到您的版本。此示例使用CASE表達式和聚合函數:

SELECT Fishtype, 
    sum(case when FishAge_Years = 3 then AvgLength else 0 end) as [3], 
    sum(case when FishAge_Years = 4 then AvgLength else 0 end) as [4], 
    sum(case when FishAge_Years = 5 then AvgLength else 0 end) as [5] 
FROM dbo.AverageFishLength 
GROUP BY Fishtype, ID; 

,因爲即使你沒有在最終名單中ID做,它仍然被並因爲用於組的結果將被扭曲,他們是獨一無二的,你會得到多行。

解決這個當使用PIVOT最簡單的方法是使用子查詢:

SELECT Fishtype , 
     [3] AS [3 Years Old] , 
     [4] AS [4 Years Old] , 
     [5] AS [5 Years Old] 
FROM 
(
    SELECT Fishtype, 
    AvgLength, 
    FishAge_Years 
    FROM dbo.AverageFishLength 
) d 
PIVOT 
( 
    SUM(AvgLength) 
    FOR FishAge_Years IN ([3], [4], [5]) 
) AS PivotTbl; 

在這個版本中,你只能回到你的實際需要,並從表中所需的列 - 這排除ID所以它會不能用於分組數據。

+0

好吧,我明白了。如果它在語法中更透明,或者如果通過從SELECT中排除某些列而不必從子查詢中排除某些列,它會很好。感謝您的詳細解釋。 –

+0

@ Dave.Gugg它實際上在文檔中,請參閱我的編輯。它隱藏在['FROM']的文檔中(http://technet.microsoft.com/en-us/library/ms177634%28v=sql.105%29.aspx)。 – Taryn

+3

(+1)這幾天我很少使用'PIVOT'。手動方法通常更加明確,可以更容易閱讀,併產生完全相同的執行計劃。 –

相關問題