it-swarm.com.de

Wie verwende ich COALESCE mit mehreren Zeilen und ohne vorangestelltes Komma?

Ich versuche Folgendes zu erreichen:

California | Los Angeles, San Francisco, Sacramento
Florida    | Jacksonville, Miami

Leider bekomme ich ", Los Angeles, San Francisco, Sacramento, Jacksonville, Miami"

Ich kann meine gewünschten Ergebnisse mit der STUFF-Funktion erzielen, habe mich aber gefragt, ob es eine sauberere Möglichkeit gibt, dies mit COALESCE zu tun?

STATE       | CITY
California  | San Francisco
California  | Los Angeles
California  | Sacramento
Florida     | Miami
Florida     | Jacksonville 


DECLARE @col NVARCHAR(MAX);
SELECT @col= COALESCE(@col, '') + ',' + city
FROM tbl where city = 'California';
SELECT @col;

Vielen Dank

29
user2732180

Dies könnte der sauberere Ansatz sein, den Sie suchen. Überprüfen Sie grundsätzlich, ob die Variable noch initialisiert wurde. Wenn dies nicht der Fall ist, setzen Sie es auf die leere Zeichenfolge und fügen Sie die erste Stadt hinzu (kein führendes Komma). Wenn dies der Fall ist, fügen Sie ein Komma und dann die Stadt hinzu.

DECLARE @col nvarchar(MAX);
SELECT @col = COALESCE(@col + ',', '') + city
  FROM dbo.tbl WHERE state = 'California';

Dies funktioniert natürlich nur zum Auffüllen einer Variablen pro Status. Wenn Sie die Liste für jeden Status einzeln abrufen, gibt es eine bessere Lösung auf einmal:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

Ergebnisse:

state       cities
----------  --------------------------------------
California  San Francisco, Los Angeles, Sacramento  
Florida     Miami, Jacksonville

So bestellen Sie nach Städtenamen in jedem Bundesland:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    ORDER BY city
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

In Azure SQL Database oder SQL Server 2017+ können Sie die neue STRING_AGG() function verwenden:

SELECT [state], cities = STRING_AGG(city, N', ')
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

Und sortiert nach Städtenamen:

SELECT [state], cities = STRING_AGG(city, N', ') 
                         WITHIN GROUP (ORDER BY city)
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];
47
Aaron Bertrand

Nur um zu Aarons Antwort oben hinzuzufügen ...

Seien Sie sich bewusst, dass ein ORDER BY wird möglicherweise unterbrochen, indem nur das letzte Element in Ihre Abfrage aufgenommen wird. In meinem Fall habe ich nicht gruppiert, also nicht sicher, ob das einen Unterschied macht. Ich verwende SQL 2014. In meinem Fall habe ich so etwas wie Wert1, Wert2, Wert3 ... aber mein Ergebnis in der Variablen war nur Wert3.


Aaron kommentierte, um zu sagen:

Dies wurde mindestens viermal bei Connect gemeldet:

  1. In Variable Verkettung und Reihenfolge nach Filtern ergibt sich (wie wo Bedingung)
  2. (n) varchar-Erstellung aus ResultSet schlägt fehl, wenn ORDER BY hinzugefügt wird
  3. Das Zuweisen einer lokalen Variablen aus einem geordneten SELECT mit CROSS APPLYs und einer Tabellenwertfunktion gibt nur den letzten Wert zurück
  4. Beim Verketten von varchar (max)/nvarchar (max) -Werten aus einer Tabellenvariablen werden möglicherweise falsche Ergebnisse zurückgegeben, wenn nach einer Nicht-Primärschlüsselspalte gefiltert und sortiert wird

Beispielantwort von Microsoft:

Das Verhalten, das Sie sehen, ist beabsichtigt. Die Verwendung von Zuweisungsoperationen (Verkettung in diesem Beispiel) in Abfragen mit der ORDER BY-Klausel weist ein undefiniertes Verhalten auf.

Die Antwort verweist auch auf KB 287515:

PRB: Ausführungsplan und Ergebnisse aggregierter Verkettungsabfragen hängen vom Ausdrucksort ab

Die Lösung besteht darin, FOR XML PATH (der zweite Ansatz in Aarons Antwort), wenn die Reihenfolge der Verkettung wichtig ist und natürlich, wenn Sie sicher sein möchten, dass alle Werte enthalten sind. Siehe auch:

nvarchar Verkettung/Index/nvarchar (max) unerklärliches Verhalten bei Stapelüberlauf

7
ebol2000