Verlässliche STRING_AGG-Ergebnisse in SQL Server
Erzeugen Sie geordnete Textlisten mit klaren Regeln für Dubletten, fehlende Werte und Länge und wählen Sie für strukturierte Daten das passende Format.
Eine kommagetrennte Liste wirkt wie reine Darstellung, hängt aber von mehreren Datenentscheidungen ab. Welche Zeilen gehören zusammen? Sind doppelte Werte gewünscht? Braucht ein fehlender Wert einen Platzhalter? Ist die Reihenfolge eindeutig? STRING_AGG vereinfacht das Zusammenfügen, beantwortet diese Fragen jedoch nicht.
Die Beispiele benötigen SQL Server 2017 oder neuer. WITHIN GROUP für eine geordnete Liste setzt mindestens Kompatibilitätsgrad 110 voraus. Prüfen Sie beide Einstellungen, wenn dieselbe Anweisung in verschiedenen Umgebungen unterschiedlich funktioniert.
Reihenfolge und fehlende Werte festlegen
Die Übungsdaten enthalten absichtlich eine doppelte Bezeichnung und NULL.
DECLARE @Tags table (DocumentId int, TagId int, Tag nvarchar(100));
INSERT @Tags VALUES
(1, 1, N'Tuning'), (1, 2, N'Backup'), (1, 3, N'Tuning'),
(1, 4, NULL), (2, 5, N'Security');
SELECT DocumentId,
STRING_AGG(CONVERT(nvarchar(max), Tag), N', ')
WITHIN GROUP (ORDER BY Tag, TagId) AS TagList
FROM @Tags
GROUP BY DocumentId;
Dokument 1 liefert bei der dargestellten alphabetischen Sortierung Backup, Tuning, Tuning. NULL erzeugt weder Text noch ein zusätzliches Trennzeichen. Dokument 2 liefert Security. STRING_AGG entfernt keine Dubletten. Ein äußeres ORDER BY sortiert die Ergebnisgruppen, nicht deren einzelne Listeneinträge.
WITHIN GROUP definiert die innere Reihenfolge. TagId entscheidet bei gleich verglichenen Bezeichnungen. Wenn das Geschäft die Reihenfolge der Zuweisung erwartet, verwenden Sie eine entsprechende gespeicherte Sequenz. Kollation beeinflusst Vergleiche und die Position von Akzenten oder verschiedener Großschreibung. Prüfen Sie reale mehrsprachige Eingaben.
NULL und eine leere Zeichenfolge sind nicht dasselbe. NULL wird ausgelassen; eine leere Zeichenfolge bleibt ein Wert und kann ein scheinbar unerklärliches Trennzeichen erzeugen. Vereinbaren Sie, wo leere oder ausschließlich aus Leerzeichen bestehende Werte normalisiert werden. Bedeutungsvolle Codes sollten nicht nur für eine schönere Anzeige verändert werden.
Ein Platzhalter für fehlende Werte muss vor der Aggregation eingesetzt werden. Er darf nicht mit echten Daten verwechselt werden. Alternativ kann ein strukturiertes Format ein echtes null erhalten. Eine Anzeige wie Unbekannt ersetzt nicht die Information, dass der Quellwert fehlt.
Auf der richtigen Ebene deduplizieren
Für eine Liste eindeutiger Bezeichnungen werden Dubletten vor dem Zusammenfügen entfernt.
;WITH DistinctTags AS (
SELECT DISTINCT DocumentId, Tag
FROM @Tags
WHERE Tag IS NOT NULL
)
SELECT DocumentId,
STRING_AGG(CONVERT(nvarchar(max), Tag), N', ')
WITHIN GROUP (ORDER BY Tag) AS TagList
FROM DistinctTags
GROUP BY DocumentId;
Dokument 1 liefert jetzt Backup, Tuning. DISTINCT gilt gemeinsam für DocumentId und Tag. Dieselbe Bezeichnung bleibt deshalb bei anderen Dokumenten erhalten. Eine globale Entfernung ohne Dokumentzuordnung würde die Beziehung zerstören.
Untersuchen Sie zunächst die Joins. Wenn ein Dokument gleichzeitig mehrere Kommentare und mehrere Tags besitzt, können sich die Tags im Zwischenergebnis vervielfachen. DISTINCT am Ende versteckt dies möglicherweise, während andere Summen falsch bleiben. Aggregieren Sie die Tag-Beziehung separat und verbinden Sie erst das Ergebnis mit einer Zeile je Dokument.
Auch die Gleichheitsregel beeinflusst die Entfernung von Dubletten. Unter einer unempfindlichen Kollation können verschiedene Schreibweisen zusammenfallen. Falls eine bevorzugte Anzeigeform erforderlich ist, braucht sie eine eigene Regel. DISTINCT allein entscheidet nicht fachlich, welche gleichwertige Schreibweise kanonisch sein soll.
Länge und Übergabeformat kontrollieren
Konvertieren Sie den Eingabeausdruck vor STRING_AGG nach nvarchar(max), wenn lange Ergebnisse legitim sind. Der Ergebnistyp wird aus der Eingabe abgeleitet. Eine Konvertierung nach fertiger Aggregation verhindert deren vorherige Längenbegrenzung nicht. Auch der Typ des Trennzeichens muss passen.
Ein großer Datentyp ist keine Aufforderung zu unbegrenzten Antworten. Hunderttausende Beziehungen können erhebliche Speicherarbeit und Netzlast erzeugen. Setzen Sie praktische Grenzen, liefern Sie Einträge seitenweise oder bieten Sie für große Gruppen einen eigenen Export.
Eine Kommaliste ist kein verlustfreies Austauschformat, wenn Werte selbst Kommas, Anführungszeichen oder Zeilenumbrüche enthalten. FOR JSON kann Grenzen und Maskierung erhalten. Die Liste sollte ebenso wenig die normalisierte Beziehung ersetzen, wenn einzelne Tags weiter gefiltert oder geändert werden müssen.
Prüfen Sie Dubletten, NULL, leere Werte, fremdsprachige Texte, Trennzeichen im Inhalt und lange Ergebnisse. Bei scheinbarer Abschneidung vergleichen Sie die tatsächliche Datenbanklänge mit der Anzeigegrenze des Clients. So bleibt die Bedeutung bis zum Empfänger nachvollziehbar.
Technische Referenzen: Microsoft Learn: STRING_AGG · Microsoft Learn: FOR JSON.