2011-07-19 4 views
1

行と列が混在しているテーブルがありません。完全に他のいくつかのデザイン。しかし、そのミスは20年前、他の誰かの時計であった。SQL行から列へ、PIVOTはおそらく動作しますが、複数の列ではどうなるかわかりません

今、私は無数の自己結合で望んでいるビューを達成しています。これは痛いほど遅いです。

以下は、現時点では私がやっている方法を設定します。これらの結果を得るために

declare @client table 
(
    clientNumber int, 
    name varchar(10) 
) 

insert into @client values (1, 'Bob'); 
insert into @client values (2, 'Alice'); 

declare @options table 
(
    clientNumber int, 
    optionKey varchar(4), 
    optionValue1 int, 
    optionValue2 int, 
    optionValue3 int 
) 
insert into @options values (1, 'optA', 1, 1, 0); 
insert into @options values (1, 'optB', 0, 1, 0); 
insert into @options values (2, 'optA', 1, 1, 1); 
insert into @options values (2, 'optC', 0, 0, 1); 

select c.clientNumber, c.name, 
     oA.optionValue1 as [Graduated], 
     oA.optionValue2 as [Employed], 
     oA.optionValue3 as [Married], 
     oB.optionValue1 as [HasPets], 
     oB.optionValue2 as [LikesThai], 
     oB.optionValue3 as [MathWiz], 
     oC.optionValue1 as [DrvLicense], 
     oC.optionValue2 as [Registered], 
     oC.optionValue3 as [Outdoorsy] 
    from @client c 
    left outer join @options oA 
     on oA.clientNumber = c.clientNumber and oA.optionKey = 'optA' 
    left outer join @options oB 
     on oB.clientNumber = c.clientNumber and oB.optionKey = 'optB' 
    left outer join @options oC 
     on oC.clientNumber = c.clientNumber and oC.optionKey = 'optC' 

を:

result set from above query

結果セットは、私がしたい正確に何です。すべてのクライアントにA、B、またはCレコードがあるわけではないので、結果セットのnullは問題ありません。私は検索のしばらくしてこのような例を見つけることができないので、私は確信していませんPIVOT本当に私が探しているものです。提案?

更新: これは同じ結果をもたらすようです。私はもっ​​と大きなケースでそれをテストして、すべての自己結合より速いかどうかを調べるつもりです。 (私はそれが疑わしい)。私はまだピボットで間違った木を鳴らしているかどうか知りたいです。

select clientNumber, 
    Min(Case o.optionKey when 'optA' then o.optionValue1 end) [Graduated], 
    Min(Case o.optionKey when 'optA' then o.optionValue2 end) [Employed], 
    Min(Case o.optionKey when 'optA' then o.optionValue3 end) [Married], 
    Min(Case o.optionKey when 'optB' then o.optionValue1 end) [HasPets], 
    Min(Case o.optionKey when 'optB' then o.optionValue2 end) [LikesThai], 
    Min(Case o.optionKey when 'optB' then o.optionValue3 end) [MathWix], 
    Min(Case o.optionKey when 'optC' then o.optionValue1 end) [DrvLicense], 
    Min(Case o.optionKey when 'optC' then o.optionValue2 end) [Registered], 
    Min(Case o.optionKey when 'optC' then o.optionValue3 end) [Outdoorsy] 
    from @options o 
    group by clientnumber 

答えて

2

かもしれません。ここのオプションのカップルです。どちらのソリューションも、データをピボットする技術を使用しています。最初の解決策はNULLを0に変更します。

SELECT c.clientNumber, c.name, 
    MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue1 ELSE 0 END) AS [Graduated], 
    MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue2 ELSE 0 END) AS [Employed], 
    MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue3 ELSE 0 END) AS [Married], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue1 ELSE 0 END) AS [HasPets], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue2 ELSE 0 END) AS [LikesThai], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue3 ELSE 0 END) AS [MathWiz], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue1 ELSE 0 END) AS [DrvLicense], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue2 ELSE 0 END) AS [Registered], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue3 ELSE 0 END) AS [Outdoorsy] 
FROM @client c 
LEFT OUTER JOIN @options o 
    ON o.clientNumber = c.clientNumber 
GROUP BY c.clientNumber, c.name 
ORDER BY c.clientNumber, c.name 

2番目の解決策はNULL値を保持します。ただし、MAX関数がBITデータ型で失敗するため、BITからTINYINTへの明示的な型変換が必要です。

SELECT c.clientNumber, c.name, 
    MAX(CASE WHEN o.optionKey = 'optA' THEN CAST (o.optionValue1 AS TINYINT) END) AS [Graduated], 
    MAX(CASE WHEN o.optionKey = 'optA' THEN CAST (o.optionValue2 AS TINYINT) END) AS [Employed], 
    MAX(CASE WHEN o.optionKey = 'optA' THEN CAST (o.optionValue3 AS TINYINT) END) AS [Married], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN CAST (o.optionValue1 AS TINYINT) END) AS [HasPets], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN CAST (o.optionValue2 AS TINYINT) END) AS [LikesThai], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN CAST (o.optionValue3 AS TINYINT) END) AS [MathWiz], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN CAST (o.optionValue1 AS TINYINT) END) AS [DrvLicense], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN CAST (o.optionValue2 AS TINYINT) END) AS [Registered], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN CAST (o.optionValue3 AS TINYINT) END) AS [Outdoorsy] 
FROM @client c 
LEFT OUTER JOIN @options o 
    ON o.clientNumber = c.clientNumber 
GROUP BY c.clientNumber, c.name 
ORDER BY c.clientNumber, c.name 
+0

ああ、私はおそらくこのようなものに行くでしょう。そして上記の@optionsテーブルで間違いを犯しました。それらは実際には 'bit'の代わりに' int's(ある種のものか別のもの)であったはずです。 –

0

私は、その性能についてはよく分からないが、私はそれをこのようにします:

select c.clientNumber, c.name, 
    oA.optionValue1 as [Graduated], 
    oA.optionValue2 as [Employed], 
    oA.optionValue3 as [Married], 
    oB.optionValue1 as [HasPets], 
    oB.optionValue2 as [LikesThai], 
    oB.optionValue3 as [MathWiz], 
    oC.optionValue1 as [DrvLicense], 
    oC.optionValue2 as [Registered], 
    oC.optionValue3 as [Outdoorsy] 
from @client c 
    OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optA' And clientnumber = c.clientnumber) oA 
    OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optB' And clientnumber = c.clientnumber) oB 
    OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optC' And clientnumber = c.clientnumber) oC 

またはCTEが有用

with t as 
(select oA.ClientNumber, 
    oA.optionValue1 as [Graduated], 
    oA.optionValue2 as [Employed], 
    oA.optionValue3 as [Married], 
    oB.optionValue1 as [HasPets], 
    oB.optionValue2 as [LikesThai], 
    oB.optionValue3 as [MathWiz], 
    oC.optionValue1 as [DrvLicense], 
    oC.optionValue2 as [Registered], 
    oC.optionValue3 as [Outdoorsy] 
from 
    (SELECT * FROM @options WHERE optionkey = 'optA') oA 
    OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optB' And clientnumber = oA.clientnumber) oB 
    OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optC' And clientnumber = oA.clientnumber) oC) 

select c.clientNumber, c.name, 
    t.[Graduated], 
    t.[Employed], 
    t.[Married], 
    t.[HasPets], 
    t.[LikesThai], 
    t.[MathWiz], 
    t.[DrvLicense], 
    t.[Registered], 
    t.[Outdoorsy] 
from @client c join t on c.clientnumber = t.clientnumber 
+0

パフォーマンスヒットは繰り返しセルフジョインにあると思います。 (現実のテーブルには約15個の「オプションキー」の値があり、テーブルには約100,000レコードがあります) –

+0

一時テーブルの使用やインデックスビューの作成はどうですか? – THEn

+0

現在、この混乱はビューにインストールされています。しかし、テンポラリ・テーブル(またはビュー)は、データ・セットを複数回通過せずにテーブルに物を入れる方法の問題を解決しません。 –

関連する問題