15

この構造のテーブルがあります。

UserID  | UserName  | AnswerToQuestion1 | AnswerToQuestion2 | AnswerToQuestion3
1       | John      | 1                 | 0                 | 1
2       | Mary      | 1                 | 1                 | 0

次のような結果セットを取得するために使用するSQLクエリがわかりません。

UserID  | UserName  | QuestionName      | Response
1       | John      | AnswerToQuestion1 | 1
1       | John      | AnswerToQuestion2 | 0
1       | John      | AnswerToQuestion3 | 1
2       | Mary      | AnswerToQuestion1 | 1
2       | Mary      | AnswerToQuestion2 | 1
2       | Mary      | AnswerToQuestion3 | 0

3つの列を3つの別々の行に分割しようとしています。これは可能ですか?

4

3 に答える 3

8
SELECT
   Y.UserID,
   Y.UserName,
   QuestionName = 'AnswerToQuestion' + X.Which,
   Response =
      CASE X.Which
      WHEN '1' THEN AnswerToQuestion1
      WHEN '2' THEN AnswerToQuestion2
      WHEN '3' THEN AnswerToQuestion3
      END
FROM
   YourTable Y
   CROSS JOIN (SELECT '1' UNION ALL SELECT '2' UNION ALL SELECT '3') X (Which)

これはUNPIVOTと同等に機能し(場合によっては優れています)、SQL2000でも機能します。

質問の類似性を利用してQuestionName列を作成しましたが、もちろんこれはさまざまな質問名で機能します。

質問のリストが長い場合、または質問名が長い場合は、Xテーブルの2つの列(1つは質問番号用、もう1つは質問名用)を試してみることができます。または、質問のリストを含むテーブルがすでにある場合は、それにクロスジョインします。一部の質問がNULLの場合、最も簡単なのは、上記のクエリをCTEまたは派生テーブルに配置してから、を追加することWHERE Response IS NOT NULLです。

于 2010-09-10T04:38:34.457 に答える
6

SQL Server 2005以降を想定すると、UNPIVOTを使用できます

;with YourTable as
(
SELECT 1 UserID,'John' UserName,1 AnswerToQuestion1,0 AnswerToQuestion2,1 AnswerToQuestion3 
UNION ALL
SELECT 2, 'Mary', 1, 1, 0
)
SELECT UserID, UserName, QuestionName, Response
FROM YourTable
UNPIVOT
   (Response FOR QuestionName IN 
      (AnswerToQuestion1, AnswerToQuestion2,AnswerToQuestion3)
)AS unpvt;
于 2010-09-09T16:28:05.163 に答える
6

Inside Microsoft SQL Server 2008:T- SQLQueryingのItzikBen -Ganによると、SQL Serverは、テーブルのピボットを解除するときに3つの手順を実行します。

  1. コピーを生成する
  2. 要素を抽出する
  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

これらの手順に従うと、次のことができます

  1. 各AnswerToQuestion列名に対してテーブル内のすべての行をクロス結合して、行のコピーを取得します
  2. ソース列とQuestionNameの一致に基づいて応答列にデータを入力します
  3. 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
于 2010-09-10T05:57:54.860 に答える