Inside Microsoft SQL Server 2008:T- SQLQueryingのItzikBen -Ganによると、SQL Serverは、テーブルのピボットを解除するときに3つの手順を実行します。
- コピーを生成する
- 要素を抽出する
- NULLのある行を削除する
ステップ1:コピーを生成する
ピボット解除されている各列の元のテーブルの各行のコピーを持つ仮想テーブルが作成されます。また、列名の文字列が新しい列に格納されます(これをQuestionName列と呼びます)。*注:プロセス全体を表示するために、列の1つの値をNULLに変更しました。
UserID UserName AnswerTo1 AnswerToQ2 AnswerToQ3 QuestionName
1 John 1 0 1 AnswerToQuestion1
1 John 1 0 1 AnswerToQuestion2
1 John 1 0 1 AnswerToQuestion3
2 Mary 1 NULL 1 AnswerToQuestion1
2 Mary 1 NULL 1 AnswerToQuestion2
2 Mary 1 NULL 1 AnswerToQuestion3
ステップ2:要素を抽出する
次に、QuestionName列の文字列値に対応するソース列の値ごとに新しい行を作成する別のテーブルが作成されます。値は新しい列に格納されます(これを応答列と呼びます)。
UserID UserName QuestionName Response
1 John AnswerToQuestion1 1
1 John AnswerToQuestion2 0
1 John AnswerToQuestion3 1
2 Mary AnswerToQuestion1 1
2 Mary AnswerToQuestion2 NULL
2 Mary AnswerToQuestion3 1
ステップ3:NULLSのある行を削除する
この手順では、[応答]列にnull値を使用して作成された行を除外します。つまり、AnswerToQuestion列のいずれかにnull値がある場合、それはピボットされていない行として表されません。
UserID UserName QuestionName Response
1 John AnswerToQuestion1 1
1 John AnswerToQuestion2 0
1 John AnswerToQuestion3 1
2 Mary AnswerToQuestion1 1
2 Mary AnswerToQuestion3 1
これらの手順に従うと、次のことができます
- 各AnswerToQuestion列名に対してテーブル内のすべての行をクロス結合して、行のコピーを取得します
- ソース列とQuestionNameの一致に基づいて応答列にデータを入力します
- UNPIVOTを使用せずに同じ結果を得るには、NULLを削除してください。
以下の例:
DECLARE @t1 TABLE (UserID INT, UserName VARCHAR(10), AnswerToQuestion1 INT,
AnswertoQuestion2 INT, AnswerToQuestion3 INT
)
INSERT @t1 SELECT 1, 'John', 1, 0, 1 UNION ALL SELECT 2, 'Mary', 1, NULL, 1
SELECT
UserID,
UserName,
QuestionName,
Response
FROM (
SELECT
UserID,
UserName,
QuestionName,
CASE QuestionName
WHEN 'AnswerToQuestion1' THEN AnswerToQuestion1
WHEN 'AnswerToQuestion2' THEN AnswertoQuestion2
ELSE AnswerToQuestion3
END AS Response
FROM @t1 t1
CROSS JOIN (
SELECT 'AnswerToQuestion1' AS QuestionName
UNION ALL SELECT 'AnswerToQuestion2'
UNION ALL SELECT 'AnswerToQuestion3'
) t2
) t3
WHERE Response IS NOT NULL