2009-07-27 24 views
1

Ich habe eine Tabelle und möchte ihre Zeilen in Spalten umwandeln, ähnlich wie eine Pivot-Tabelle, aber ohne Zusammenfassung.SQL-Zeilen zu Spalten

Zum Beispiel habe ich die folgenden Tabellen:

Question 
--QuestionID 
--QuestionText 

Response 
--ResponseID 
--ResponseText 
--QuestionID 

Grundsätzlich möchte ich in der Lage sein, eine dynamische Tabelle wie etwas zu schaffen:

Question 1 Text | Question 2 Text | Question 3 Text 
--------------------------------------------------- 
Response 1.1 Text | Response Text 1.2 | Response 1.3 
Response 2.1 Text | Response Text 2.2 | Response 2.3 
Response 3.1 Text | Response Text 3.2 | Response 3.3 
Response 4.1 Text | Response Text 4.2 | Response 4.3 

Die wichtigste Voraussetzung wäre, weiß ich nicht zur Entwurfszeit, was der Fragetext sein wird.

Bitte kann jemand helfen - Ich ziehe mir die Haare aus: O

Im Wesentlichen können Sie garantieren, dass es in diesem Szenario eine Antwort für jede entsprechende Frage.

+0

Welcher Datenbankserver? – AakashM

+1

Es wird SQL Server sein. Es ist immer verdammt SQL Server. – skaffman

+0

Ja, SQL Server. Ich tat es, was ich brauchte, um das XML zu verwenden, und erreichte die Aggregation durch eine Funktion – IThasTheAnswer

Antwort

7

Sie können es nicht mit SQL (außer mit dynamischen Abfragen) tun, es sei denn, Sie kennen die Anzahl der Spalten (d. H. Fragen) in Entwurfszeit.

Sie sollten die Daten, die Sie in tabellarischer Form möchten ziehen und es dann auf Client-Seite bearbeiten:

SELECT * 
FROM Question 
LEFT OUTER JOIN 
     Response 
ON  Response.QuestionId = Question.QuestionID 

oder, ist dies wahrscheinlich, (in SQL Server 2005+, Oracle 8i+ und PostgreSQL 8.4+):

SELECT * 
FROM (
     SELECT q.*, ROW_NUMBER() OVER (ORDER BY questionID) AS rn 
     FROM Question q 
     ) q 
LEFT OUTER JOIN 
     (
     SELECT r.*, ROW_NUMBER() OVER (PARTITION BY questionID ORDER BY ResponseID) AS rn 
     FROM Response r 
     ) r 
ON  r.QuestionId = q.QuestionID 
     AND q.rn = r.rn 
ORDER BY 
     q.rn, q.QuestionID 

Die letzte Abfrage liefert Ihnen Ergebnisse in diesem Formular (vorausgesetzt, Sie haben 4 Fragen):

rn  question  response 
---   ---   --- 
1  Question 1 Response 1.1 
1  Question 2 Response 2.1 
1  Question 3 Response 3.1 
1  Question 4 Response 4.1 
2  Question 1 Response 1.2 
2  Question 2 Response 2.2 
2  Question 3 NULL 
2  Question 4 Response 4.2 
3  Question 1 NULL 
3  Question 2 NULL 
3  Question 3 Response 3.3 
3  Question 4 NULL 

, dies ist die Ausgabe der Daten in Tabellenform, wobei rn die Zeilennummer markiert.

Jedes Mal, wenn Sie die rn Änderung auf dem Client sehen, schließen Sie einfach <tr> und öffnen Sie die neue.

Sie sicher Ihre <td> ist einer pro resultset Zeile setzen können, da gleiche Anzahl oder Zeilen garantiert für jeden rn

zurückgegeben werden Frage ist ziemlich häufig gefragt.

SQL nur kein richtiges Werkzeug, um Daten mit dynamischer Anzahl der Spalten zurückzugeben.

SQL arbeitet auf Mengen, und das Spaltenlayout ist eine implizite Eigenschaft einer Menge.

Sie sollten das Layout der Menge definieren, die Sie in Entwurfszeit erhalten möchten, so wie Sie den Datentyp einer Variable in C definieren.

C arbeitet mit streng definierten Variablen, arbeitet SQL mit streng definierten Mengen.

Beachten Sie, dass ich nicht sage, dass es die beste mögliche Methode ist. Es ist einfach so, SQL funktioniert.

Update:

In SQL Server, können Sie die Tabelle in HTML Form ziehen direkt aus der Datenbank:

WITH a AS 
     (
     SELECT a.*, ROW_NUMBER() OVER (PARTITION BY question_id ORDER BY id) AS rn 
     FROM answer a 
     ), 
     rows AS (
     SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn 
     FROM answer a 
     WHERE question_id = 
       (
       SELECT TOP 1 question_id 
       FROM answer a 
       GROUP BY 
         question_id 
       ORDER BY 
         COUNT(*) DESC 
       ) 
     ) 
SELECT (
     SELECT COALESCE(a.value, '') 
     FROM question q 
     LEFT JOIN 
       a 
     ON  a.rn = rows.rn 
       AND a.question_id = q.id 
     FOR XML PATH ('td'), TYPE 
     ) AS tr 
FROM rows 
FOR XML PATH(''), ROOT('table') 

Sehen Sie diesen Eintrag in meinem Blog für weitere Informationen:

+0

OK, danke für die Antwort. Ich hoffe, eine Lösung zu finden, die bedeutet, dass ich mit einer Tabelle ende, um dann Gruppierung und Aggregation durchzuführen. Ich kann die Anzahl der Spalten zur Entwurfszeit nicht kennen, da die Spalten auf benutzergesteuerten Daten basieren. – IThasTheAnswer

+0

@Tunic: siehe post update – Quassnoi

+0

Danke. Ich habe bereits eine ähnliche Lösung auf meiner Client-Seite, weil ich XSLT verwende, um die Daten zu verarbeiten. Das Problem ist, dass ich letztendlich die Kombinationen der Ergebnisse kennen muss. Deshalb wollte ich, dass Tabellendaten aus SQL dann gruppieren und aggregieren können. – IThasTheAnswer

0

Gruppieren und aggregieren Sie zuerst, indem Sie Quassnois Antwort als Zwischenergebnis verwenden.

Die Kreuztabellierung sollte nur durchgeführt werden, wenn Sie nicht mehr Set-orientierte Operationen an den Ergebnissen vornehmen. Einige SQL-Dialekte haben Keywords wie PIVOT, TRANSFORM oder CROSSTABULATE, um dies zu erreichen, aber Sie sind wahrscheinlich besser dran mit XSLT.

+0

Das Problem ist - was passiert, wenn Sie das Ergebnis der Kreuztabelle aggregieren möchten? Der einzige Weg, den ich bis jetzt habe, ist, eine Funktion zu verwenden, um die Felder in eine konkatierte Zeichenkette zu verwandeln - fühlt sich sehr schmutzig an – IThasTheAnswer

Verwandte Themen