Tabelle ist:
+----+------+
| Id | Name |
+----+------+
| 1 | aaa |
| 1 | bbb |
| 1 | ccc |
| 1 | ddd |
| 1 | eee |
+----+------+
Erforderliche Ausgabe:
+----+---------------------+
| Id | abc |
+----+---------------------+
| 1 | aaa,bbb,ccc,ddd,eee |
+----+---------------------+
Abfrage:
SELECT ID,
abc = STUFF(
(SELECT ',' + name FROM temp1 FOR XML PATH ('')), 1, 1, ''
)
FROM temp1 GROUP BY id
Diese Abfrage funktioniert ordnungsgemäß. Aber ich brauche nur die Erklärung, wie es funktioniert oder gibt es einen anderen oder kurzen Weg, dies zu tun.
Ich bin sehr verwirrt, das zu verstehen.
sql
sql-server
database
Puneet Chawla
quelle
quelle
ID
ist das in einer anderen Tabelle verschiedener Entitäten einzigartig, und diese Tabelle speichert Dinge, die zu ihnen gehören.Antworten:
So funktioniert es:
1. Holen Sie sich eine XML-Elementzeichenfolge mit FOR XML
Durch Hinzufügen von FOR XML PATH am Ende einer Abfrage können Sie die Ergebnisse der Abfrage als XML-Elemente ausgeben, wobei der Elementname im PATH-Argument enthalten ist. Zum Beispiel, wenn wir die folgende Anweisung ausführen würden:
Durch Übergabe einer leeren Zeichenfolge (FOR XML PATH ('')) erhalten wir stattdessen Folgendes:
2. Entfernen Sie das führende Komma mit STUFF
Die STUFF-Anweisung "stopft" buchstäblich eine Zeichenfolge in eine andere und ersetzt Zeichen innerhalb der ersten Zeichenfolge. Wir verwenden sie jedoch einfach, um das erste Zeichen der resultierenden Werteliste zu entfernen.
Die Parameter von
STUFF
sind:Am Ende haben wir also:
3. Treten Sie der ID bei, um eine vollständige Liste zu erhalten
Als nächstes fügen wir dies einfach in die Liste der IDs in der temporären Tabelle ein, um eine Liste der IDs mit Namen zu erhalten:
Und wir haben unser Ergebnis:
Hoffe das hilft!
quelle
LISTAGG
Hinsicht voraus, indem es Funktionen in Oracle 11gR2 einführte . Ich vermisse diese Funktionalität an Tagen, an denen ich sie stattdessen verwenden muss. techonthenet.com/oracle/functions/listagg.phplist
Jahrzehnten eine Funktion. Leider hat Microsoft SQLServer stattdessen auf Sybases ASE basiert und sich erst letztes Jahr mit einer Listenfunktion beschäftigt. Ich stimme zu - es ist umwerfend. Und dann nennen sie esstring_agg
. Ich hätte gedacht,list
war ziemlich offensichtlich.Dieser Artikel behandelt verschiedene Möglichkeiten zum Verketten von Zeichenfolgen in SQL, einschließlich einer verbesserten Version Ihres Codes, die die verketteten Werte nicht XML-codiert.
Beginnen Sie mit der inneren Abfrage, um zu verstehen, was passiert:
Da Sie angeben
FOR XML
, erhalten Sie eine einzelne Zeile mit einem XML-Fragment, das alle Zeilen darstellt.Da Sie für die erste Spalte keinen Spaltenalias angegeben haben, wird jede Zeile in ein XML-Element mit dem Namen in Klammern nach dem eingeschlossen
FOR XML PATH
. Wenn Sie dies beispielsweise getan hättenFOR XML PATH ('X')
, würden Sie ein XML-Dokument erhalten, das wie folgt aussieht:Da Sie jedoch keinen Elementnamen angegeben haben, erhalten Sie nur eine Liste mit Werten:
Das
.value('.', 'varchar(max)')
ruft einfach den Wert aus dem resultierenden XML-Fragment ab, ohne XML-Codierung von "Sonderzeichen". Sie haben jetzt eine Zeichenfolge, die wie folgt aussieht:Die
STUFF
Funktion entfernt dann das führende Komma und gibt Ihnen ein Endergebnis, das wie folgt aussieht:Auf den ersten Blick sieht es ziemlich verwirrend aus, aber im Vergleich zu einigen anderen Optionen ist die Leistung recht gut.
quelle
TYPE
Direktive weist SQL an, die Daten mit demxml
Typ zurückzugeben. Ohne sie werden die Daten als zurückgegebennvarchar(max)
. Es wird hier verwendet, um XML-Codierungsprobleme zu vermeiden, wenn diename
Spalte Sonderzeichen enthält .TYPE
und.value('.', 'varchar(max)')
im Ergebnis XML-codierte Entitäten erhalten.Der PATH-Modus wird zum Generieren von XML aus einer SELECT-Abfrage verwendet
Die Ausgabe ist elementzentriertes XML, bei dem jeder Spaltenwert im resultierenden Rowset in ein Zeilenelement eingeschlossen wird. Da in der SELECT-Klausel keine Aliase für die Spaltennamen angegeben sind, stimmen die generierten untergeordneten Elementnamen mit den entsprechenden Spaltennamen in der SELECT-Klausel überein.
Für jede Zeile im Rowset wird ein Tag hinzugefügt.
Für Schritt 2: Wenn Sie eine Zeichenfolge mit der Länge Null angeben, wird das Umbruchelement nicht erzeugt.
In Schritt 4 verketten wir die Werte.
In Schritt 6 gruppieren wir das Datum nach ID.
STUFF (source_string, start, length, add_string) Parameter oder Argumente source_string Die zu ändernde Quellzeichenfolge. start Die Position in der Quellzeichenfolge, um Längenzeichen zu löschen und dann add_string einzufügen. Länge Die Anzahl der Zeichen, die aus source_string gelöscht werden sollen. add_string Die Zeichenfolge, die an der Startposition in den source_string eingefügt werden soll.
quelle
','
als Spalte angegebene Spalte in Kombination mit dem('')
After-XML-Pfad zu einer Verkettung führtSELECT 'a' FROM some_table FOR XML PATH('')
erzeugt beispielsweise :'aaaaaaa'
. Aber wenn Spaltenname angegeben wird:SELECT 'a' AS Col FROM some_table FOR XML PATH('')
Sie erhalten Ergebnis:<Col>a</Col><Col>a</Col><Col>a</Col>
In Azure SQL Database und SQL Server (ab 2017) gibt es sehr neue Funktionen, um genau dieses Szenario zu handhaben. Ich glaube, dies würde als native offizielle Methode für das dienen, was Sie mit der XML / STUFF-Methode erreichen möchten. Beispiel:
STRING_AGG - https://msdn.microsoft.com/en-us/library/mt790580.aspx
BEARBEITEN: Als ich dies ursprünglich veröffentlichte, erwähnte ich SQL Server 2016, als ich dachte, ich hätte das bei einer potenziellen Funktion gesehen, die aufgenommen werden sollte. Entweder habe ich mich falsch daran erinnert oder etwas hat sich geändert, danke für die vorgeschlagene Bearbeitung, mit der die Version repariert wurde. Außerdem ziemlich beeindruckt und war mir des mehrstufigen Überprüfungsprozesses, der mich gerade für eine letzte Option angezogen hat, nicht ganz bewusst.
quelle
In
for xml path
, wenn wir definieren einen beliebigen Wert wie[ for xml path('ENVLOPE') ]
dann werden diese Tags mit jeder Zeile hinzugefügt werden:quelle
Hier in der obigen Abfrage wird die STUFF- Funktion verwendet, um nur das erste Komma
(,)
aus der generierten XML-Zeichenfolge zu entfernen,(,aaa,bbb,ccc,ddd,eee)
dann wird es(aaa,bbb,ccc,ddd,eee)
.Und
FOR XML PATH('')
konvertiert einfach Spaltendaten in(,aaa,bbb,ccc,ddd,eee)
Zeichenfolgen, aber in PATH übergeben wir '', sodass kein XML-Tag erstellt wird.Und am Ende haben wir Datensätze mithilfe der ID- Spalte gruppiert .
quelle
Ich habe debuggt und schließlich meine "ausgestopfte" Abfrage auf normale Weise zurückgegeben.
Einfach
gibt mir den Inhalt der Tabelle zum Schreiben in eine Protokolltabelle von einem Trigger, den ich debugge.
quelle
quelle
STUFF ((SELECT different ',' + CAST (T.ID) FROM Table T wobei T.ID = 1 FOR XML PATH ('')), 1,1, '') AS Name
quelle
Ich benutze häufig mit where-Klausel
quelle