2015-01-08 20 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 

ここでの結果は以下のとおりです。私はID列を持つテーブルを作成する場合

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は、グループ化列に関して入力テーブルにグループ化演算を行い、各グループため一つの行を返します。さらに、出力には、input_tableのpivot_columnに表示されるcolumn_listで指定された各値に対して1つの列が含まれます。

お使いのバージョンは基本的にはSELECT * FROM yourtableとなっており、そのデータはPIVOTです。 ID列は最終的なSELECTリストに含まれていませんが、クエリのグループ化要素です。 PIVOTを "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'を使うことはめったにありません。手動の方法はしばしばより明白であり、おそらく読みやすく、正確に同じ実行計画になります。 –

関連する問題