Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Optimale Methode zum Verketten/Aggregieren von Zeichenfolgen

LÖSUNG

Die Definition von optimal kann variieren, aber hier erfahren Sie, wie Sie Zeichenfolgen aus verschiedenen Zeilen mit normalem Transact SQL verketten, was in Azure problemlos funktionieren sollte.

;WITH Partitioned AS
(
    SELECT 
        ID,
        Name,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Name) AS NameNumber,
        COUNT(*) OVER (PARTITION BY ID) AS NameCount
    FROM dbo.SourceTable
),
Concatenated AS
(
    SELECT 
        ID, 
        CAST(Name AS nvarchar) AS FullName, 
        Name, 
        NameNumber, 
        NameCount 
    FROM Partitioned 
    WHERE NameNumber = 1

    UNION ALL

    SELECT 
        P.ID, 
        CAST(C.FullName + ', ' + P.Name AS nvarchar), 
        P.Name, 
        P.NameNumber, 
        P.NameCount
    FROM Partitioned AS P
        INNER JOIN Concatenated AS C 
                ON P.ID = C.ID 
                AND P.NameNumber = C.NameNumber + 1
)
SELECT 
    ID,
    FullName
FROM Concatenated
WHERE NameNumber = NameCount

ERKLÄRUNG

Der Ansatz läuft auf drei Schritte hinaus:

  1. Nummerieren Sie die Zeilen mit OVER und PARTITION Gruppieren und Ordnen sie nach Bedarf für die Verkettung. Das Ergebnis ist Partitioned CTE. Wir zählen die Zeilen in jeder Partition, um die Ergebnisse später zu filtern.

  2. Mit rekursivem CTE (Concatenated ) durch die Zeilennummern iterieren (NameNumber Spalte) Hinzufügen von Name Werte zu FullName Spalte.

  3. Alle Ergebnisse außer denen mit der höchsten NameNumber herausfiltern .

Bitte beachten Sie, dass Sie, um diese Abfrage vorhersagbar zu machen, beide Gruppierungen definieren müssen (z. B. in Ihrem Szenario Zeilen mit derselben ID verkettet werden) und Sortierung (ich bin davon ausgegangen, dass Sie die Zeichenfolge vor der Verkettung einfach alphabetisch sortieren).

Ich habe die Lösung schnell auf SQL Server 2012 mit den folgenden Daten getestet:

INSERT dbo.SourceTable (ID, Name)
VALUES 
(1, 'Matt'),
(1, 'Rocks'),
(2, 'Stylus'),
(3, 'Foo'),
(3, 'Bar'),
(3, 'Baz')

Das Abfrageergebnis:

ID          FullName
----------- ------------------------------
2           Stylus
3           Bar, Baz, Foo
1           Matt, Rocks