Wie wechsle ich einfach Spalten mit Zeilen in SQL? Gibt es einen einfachen Befehl zum Transponieren?
dh drehen Sie dieses Ergebnis:
Paul | John | Tim | Eric
Red 1 5 1 3
Green 8 4 3 5
Blue 2 2 9 1
das mögen:
Red | Green | Blue
Paul 1 8 2
John 5 4 2
Tim 1 3 9
Eric 3 5 1
PIVOT
scheint für dieses Szenario zu komplex.
sql
sql-server
tsql
pivot
edezzie
quelle
quelle
Antworten:
Es gibt verschiedene Möglichkeiten, diese Daten zu transformieren. In Ihrem ursprünglichen Beitrag haben Sie angegeben, dass
PIVOT
dies für dieses Szenario zu komplex erscheint, es jedoch sehr einfach mit den FunktionenUNPIVOT
undPIVOT
in SQL Server angewendet werden kann .Wenn Sie jedoch keinen Zugriff auf diese Funktionen haben, kann dies mithilfe von
UNION ALL
toUNPIVOT
und anschließend einer Aggregatfunktion mit derCASE
Anweisung to repliziert werdenPIVOT
:Tabelle erstellen:
Union All, Aggregate und CASE Version:
Siehe SQL Fiddle mit Demo
Das
UNION ALL
führt dieUNPIVOT
Daten aus, indem die SpaltenPaul, John, Tim, Eric
in separate Zeilen umgewandelt werden. Anschließend wenden Sie die Aggregatfunktionsum()
mit dercase
Anweisung an, um die neuen Spalten für jede zu erhaltencolor
.Unpivot und Pivot Static Version:
Sowohl die
UNPIVOT
als auch diePIVOT
Funktionen in SQL Server erleichtern diese Umwandlung erheblich. Wenn Sie alle Werte kennen, die Sie transformieren möchten, können Sie sie in eine statische Version fest codieren, um das Ergebnis zu erhalten:Siehe SQL Fiddle mit Demo
Die innere Abfrage mit dem hat
UNPIVOT
die gleiche Funktion wie dieUNION ALL
. Es nimmt die Liste der Spalten undPIVOT
wandelt sie in Zeilen um. Anschließend führt es die endgültige Umwandlung in Spalten durch.Dynamische Pivot-Version:
Wenn Sie eine unbekannte Anzahl von Spalten (
Paul, John, Tim, Eric
in Ihrem Beispiel) und dann eine unbekannte Anzahl von zu transformierenden Farben haben, können Sie die Liste mit dynamischem SQL generierenUNPIVOT
und dannPIVOT
:Siehe SQL Fiddle mit Demo
Die dynamische Version fragt sowohl
yourtable
diesys.columns
Tabelle als auch die Tabelle ab, um die Liste der Elemente fürUNPIVOT
und zu generierenPIVOT
. Dies wird dann zu einer auszuführenden Abfragezeichenfolge hinzugefügt. Das Plus der dynamischen Version ist, wenn Sie eine sich ändernde Liste von habencolors
und / odernames
die Liste zur Laufzeit generiert wird.Alle drei Abfragen führen zum gleichen Ergebnis:
quelle
Dies erfordert normalerweise, dass Sie ALLE Spalten- UND Zeilenbeschriftungen im Voraus kennen. Wie Sie in der folgenden Abfrage sehen können, werden alle Beschriftungen sowohl in der UNPIVOT- als auch in der (Neu-) PIVOT-Operation vollständig aufgelistet.
MS SQL Server 2012 Schema-Setup :
Abfrage 1 :
Ergebnisse :
Zusätzliche Bemerkungen:
quelle
Ich möchte auf einige weitere Lösungen für die Transponierung von Spalten und Zeilen in SQL hinweisen.
Der erste ist - mit CURSOR. Obwohl der allgemeine Konsens in der Fachwelt darin besteht, sich von SQL Server-Cursorn fernzuhalten, gibt es immer noch Fälle, in denen die Verwendung von Cursorn empfohlen wird. Wie auch immer, Cursor bieten uns eine weitere Möglichkeit, Zeilen in Spalten zu transponieren.
Vertikale Ausdehnung
Ähnlich wie beim PIVOT kann der Cursor dynamisch mehr Zeilen anhängen, wenn Ihr Dataset um weitere Richtliniennummern erweitert wird.
Horizontale Ausdehnung
Im Gegensatz zum PIVOT zeichnet sich der Cursor in diesem Bereich aus, da er erweitert werden kann, um neu hinzugefügte Dokumente einzuschließen, ohne das Skript zu ändern.
Leistungsaufschlüsselung
Die Hauptbeschränkung beim Transponieren von Zeilen in Spalten mit CURSOR ist ein Nachteil, der mit der Verwendung von Cursorn im Allgemeinen verbunden ist - sie sind mit erheblichen Leistungskosten verbunden. Dies liegt daran, dass der Cursor für jede FETCH NEXT-Operation eine separate Abfrage generiert.
Eine andere Lösung zum Transponieren von Zeilen in Spalten ist die Verwendung von XML.
Die XML-Lösung zum Transponieren von Zeilen in Spalten ist im Grunde eine optimale Version des PIVOT, da sie die dynamische Spaltenbeschränkung berücksichtigt.
Die XML-Version des Skripts behebt diese Einschränkung durch die Verwendung einer Kombination aus XML-Pfad, dynamischem T-SQL und einigen integrierten Funktionen (z. B. STUFF, QUOTENAME).
Vertikale Ausdehnung
Ähnlich wie bei PIVOT und Cursor können neu hinzugefügte Richtlinien in der XML-Version des Skripts abgerufen werden, ohne das ursprüngliche Skript zu ändern.
Horizontale Ausdehnung
Im Gegensatz zum PIVOT können neu hinzugefügte Dokumente angezeigt werden, ohne das Skript zu ändern.
Leistungsaufschlüsselung
In Bezug auf E / A ähnelt die Statistik der XML-Version des Skripts fast der von PIVOT. Der einzige Unterschied besteht darin, dass die XML-Datei einen zweiten Scan der dtTranspose-Tabelle ausführt, diesmal jedoch aus einem logischen Lesedaten-Cache.
Weitere Informationen zu diesen Lösungen (einschließlich einiger aktueller T-SQL-Beispiele) finden Sie in diesem Artikel: https://www.sqlshack.com/multiple-options-to-transposing-rows-into-columns/
quelle
Basierend auf dieser Lösung von bluefeet ist hier eine gespeicherte Prozedur, die dynamisches SQL verwendet, um die transponierte Tabelle zu generieren. Es ist erforderlich, dass alle Felder mit Ausnahme der transponierten Spalte (der Spalte, die die Überschrift in der resultierenden Tabelle bildet) numerisch sind:
Sie können es mit der mit diesem Befehl bereitgestellten Tabelle testen:
quelle
Ich mache
UnPivot
zuerst und speichere die Ergebnisse inCTE
und verwende dieCTE
In-Pivot
Operation.Demo
quelle
Wenn Sie zu @Paco Zarates großartiger Antwort oben hinzufügen möchten, wenn Sie eine Tabelle mit mehreren Spaltentypen transponieren möchten, fügen Sie diese am Ende von Zeile 39 hinzu, sodass nur
int
Spalten transponiert werden :Hier ist die vollständige Abfrage, die geändert wird:
system_type_id
Führen Sie Folgendes aus, um andere zu finden :quelle
Ich teile gerne den Code, den ich verwende, um einen geteilten Text basierend auf der + Bluefeet-Antwort zu transponieren. In diesem Ansatz bin ich als Prozedur in MS SQL 2005 implementiert
Ich mische diese Lösung mit den Informationen zum Ordnen von Zeilen ohne Reihenfolge nach ( SQLAuthority.com ) und der Aufteilungsfunktion auf MSDN ( social.msdn.microsoft.com ).
Wenn Sie die Prozedur ausführen
Sie erhalten das nächste Ergebnis
quelle
Auf diese Weise konvertieren Sie alle Daten aus Filelds (Spalten) in Tabelle in Datensatz (Zeile).
quelle
Ich konnte die Lösung von Paco Zarate verwenden und sie funktioniert wunderbar. Ich musste eine Zeile hinzufügen ("SET ANSI_WARNINGS ON"), aber das kann etwas Einzigartiges sein, wie ich es verwendet oder genannt habe. Es gibt ein Problem mit meiner Verwendung und ich hoffe, jemand kann mir dabei helfen:
Die Lösung funktioniert nur mit einer tatsächlichen SQL-Tabelle. Ich habe es mit einer temporären Tabelle und einer speicherinternen (deklarierten) Tabelle versucht, aber mit diesen funktioniert es nicht. In meinem Aufrufcode erstelle ich eine Tabelle in meiner SQL-Datenbank und rufe dann SQLTranspose auf. Wieder funktioniert es großartig. Es ist genau das, was ich will. Hier ist mein Problem:
Damit die Gesamtlösung wirklich dynamisch ist, muss ich diese Tabelle erstellen, in der ich die vorbereiteten Informationen, die ich "on the fly" an SQLTranspose sende, vorübergehend speichere und diese Tabelle dann lösche, sobald SQLTranspose aufgerufen wird. Das Löschen der Tabelle stellt ein Problem mit meinem endgültigen Implementierungsplan dar. Der Code muss von einer Endbenutzeranwendung ausgeführt werden (eine Schaltfläche in einem Microsoft Access-Formular / -Menü). Wenn ich diesen SQL-Prozess verwende (SQL-Tabelle erstellen, SQLTranspose aufrufen, SQL-Tabelle löschen), tritt bei der Endbenutzeranwendung ein Fehler auf, da das verwendete SQL-Konto nicht zum Löschen einer Tabelle berechtigt ist.
Ich denke, es gibt einige mögliche Lösungen:
Finden Sie eine Möglichkeit, SQLTranspose mit einer temporären Tabelle oder einer deklarierten Tabellenvariablen arbeiten zu lassen.
Finden Sie eine andere Methode für die Transposition von Zeilen und Spalten heraus, für die keine tatsächliche SQL-Tabelle erforderlich ist.
Finden Sie eine geeignete Methode heraus, mit der das von meinen Endbenutzern verwendete SQL-Konto eine Tabelle löschen kann. Es ist ein einzelnes freigegebenes SQL-Konto, das in meiner Access-Anwendung codiert ist. Es scheint, dass die Berechtigung ein Privileg vom Typ dbo ist, das nicht gewährt werden kann.
Ich erkenne, dass einige davon einen anderen, separaten Thread und eine andere Frage rechtfertigen können. Da es jedoch die Möglichkeit gibt, dass eine Lösung einfach eine andere Methode zum Transponieren von Zeilen und Spalten ist, werde ich hier in diesem Thread meinen ersten Beitrag verfassen.
EDIT: Ich habe auch die Summe (Wert) durch max (Wert) in der 6. Zeile vom Ende ersetzt, wie Paco vorgeschlagen hat.
BEARBEITEN:
Ich habe etwas herausgefunden, das für mich funktioniert. Ich weiß nicht, ob es die beste Antwort ist oder nicht.
Ich habe ein schreibgeschütztes Benutzerkonto, mit dem gestresste Prozeduren ausgeführt werden und daher Berichtsausgaben aus einer Datenbank generiert werden. Da die von mir erstellte SQLTranspose-Funktion nur mit einer "legitimen" Tabelle (keine deklarierte Tabelle und keine temporäre Tabelle) funktioniert, musste ich herausfinden, wie ein schreibgeschütztes Benutzerkonto eine Tabelle erstellen (und später löschen) kann .
Ich habe festgestellt, dass es für meine Zwecke in Ordnung ist, dass das Benutzerkonto eine Tabelle erstellen darf. Der Benutzer konnte die Tabelle jedoch immer noch nicht löschen. Meine Lösung bestand darin, ein Schema zu erstellen, in dem das Benutzerkonto autorisiert ist. Wenn ich diese Tabelle dann erstelle, verwende oder lösche, verweise ich sie mit dem angegebenen Schema.
Ich habe diesen Befehl zuerst von einem 'sa'- oder' sysadmin'-Konto aus ausgegeben: CREATE SCHEMA ro AUTHORIZATION
Wenn ich auf meine "tmpoutput" -Tabelle verweise, gebe ich sie wie folgt an:
drop table ro.tmpoutput
quelle