2010-09-09 27 views
10

Ich habe eine Tabelle mit dieser Struktur.Mehrere Spalten in mehrere Zeilen teilen

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

ich kann nicht herausfinden, was ich SQL-Abfrage ein Ergebnis zu erhalten gesetzt wie folgt verwenden würde:

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 

Ich versuche, die drei Spalten in drei getrennte Reihen zu spalten. Ist das möglich?

Antwort

6
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) 

Dies führt ebenso gut auf UNPIVOT (manchmal besser) und arbeitet in SQL 2000 als auch nutzen können.

Ich habe die Ähnlichkeit der Fragen genutzt, um die QuestionName-Spalte zu erstellen, aber das funktioniert natürlich mit verschiedenen Frage-Namen.

Beachten Sie, dass Sie, wenn Ihre Liste von Fragen lang ist oder die Fragennamen lang sind, mit zwei Spalten in der X-Tabelle experimentieren können, eine für die Fragennummer und eine für den Fragennamen. Oder wenn Sie bereits eine Tabelle mit der Liste der Fragen haben, dann CROSS JOIN dazu. Wenn einige Fragen NULL sind, ist es am einfachsten, die obige Abfrage in eine CTE oder eine abgeleitete Tabelle einzufügen und dann WHERE Response IS NOT NULL hinzuzufügen.

+0

Ich bekomme 'Spalte Fragewort existiert nicht' mit diesem – hedgedandlevered

+0

Nein, meine Abfrage funktioniert gut. Sie erhalten diesen Fehler nur, wenn Sie versuchen, in der Abfrage auf den Alias ​​'QuestionName' zu ​​verweisen. Fügen Sie diese Abfrage in eine abgeleitete Tabelle ein und wählen Sie sie aus. Sie können dann Bedingungen hinzufügen. Sie verwenden SQL Server, richtig? – ErikE

+0

Oh nein, ich benutze reguläres SQL. Das sql-server-Tag wurde nicht angezeigt. Danke, am Ende herauszufinden, mit 8kb Antwort und Ihre. – hedgedandlevered

5

Unter der Annahme, SQL Server 2005+ Sie 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; 
+0

Sorry für die späte Antwort und danke Ihnen für Ihre Antwort. Gibt es Alternativen zur Verwendung des UNPIVOT-Operators? – Sandro

6

Nach Itzik Ben-Gan in Inside Microsoft SQL Server 2008: T-SQL Querying, geht SQL Server durch drei Schritte, wenn eine Tabelle unpivoting:

  1. generieren Kopien
  2. Extract Elemente
  3. entfernen Reihen mit NULLs

Schritt 1: Kopien erstellen

Eine virtuelle Tabelle wird erstellt, die eine Kopie jeder Zeile in der ORIGNAL-Tabelle für jede Spalte enthält, die aufgehoben wird. Außerdem wird eine Zeichenkette des Spaltennamens in einer neuen Spalte gespeichert (nennen Sie dies die Spalte QuestionName). * Hinweis: Ich habe den Wert in einer Ihrer Spalten auf NULL geändert, um den vollständigen Prozess anzuzeigen.

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 

Schritt 2: Extract Elemente

Dann ist eine weitere Tabelle erstellt, die für jeden Wert aus der Quellenspalte, die der Zeichenkette Wert entspricht in der Spalte QuestionName eine neue Zeile erzeugt. Der Wert wird in einer neuen Spalte gespeichert (rufen Sie die Spalte Antwort auf).

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 

Schritt 3: Entfernen Reihen mit NULLS

Dieser Schritt alle Zeilen herausfiltert, die mit Nullwerten in der Spalte Response erstellt wurden. Mit anderen Worten, Wenn eine der AnswerToQuestion-Spalten einen Nullwert hatte, wurde sie nicht als eine nicht gespielte Zeile dargestellt.

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

Wenn Sie diese Schritte ausgeführt haben, können Sie

  1. CROSS JOIN alle Zeilen in der Tabelle gegen jede AnswerToQuestion Spaltenname Zeile kopiert
  2. Füllen Sie die Spalte Response basierend auf der passenden bekommen die Quellenspalte und QuestionName
  3. Entfernen Sie die NULL, um die gleichen Ergebnisse ohne Verwendung von UNPIVOT zu erhalten.

Ein Beispiel unter:

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 
+0

Vielen Dank für die Qualität der Antwort. Ich mag deine Antwort sehr, da sie am ausführlichsten ist, aber ich muss Emtucifor vielleicht antworten, dass er nur ein paar Stunden vor dir antwortet. Vielen Dank! – Sandro

Verwandte Themen