Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Optymalny sposób łączenia/agregowania ciągów

ROZWIĄZANIE

Definicja optymalnego może się różnić, ale oto jak połączyć ciągi z różnych wierszy przy użyciu zwykłego języka Transact SQL, który powinien działać dobrze na platformie Azure.

;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

WYJAŚNIENIE

Podejście sprowadza się do trzech kroków:

  1. Numeruj wiersze za pomocą OVER i PARTITION grupowanie i porządkowanie ich według potrzeb do konkatenacji. Wynik to Partitioned CTE. Przechowujemy liczbę wierszy w każdej partycji, aby później filtrować wyniki.

  2. Używanie rekurencyjnego CTE (Concatenated ) iteruj przez numery wierszy (NameNumber kolumna) dodanie Name wartości do FullName kolumna.

  3. Odfiltruj wszystkie wyniki oprócz tych z najwyższym NameNumber .

Należy pamiętać, że aby to zapytanie było przewidywalne, należy zdefiniować oba grupowanie (na przykład wiersze scenariusza z tym samym ID są połączone) i sortowanie (założyłem, że po prostu posortujesz łańcuch alfabetycznie przed połączeniem).

Szybko przetestowałem rozwiązanie na SQL Server 2012 z następującymi danymi:

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

Wynik zapytania:

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Poprawka:„Oświadczenie BACKUP LOG jest niedozwolone, gdy model odzyskiwania jest PROSTY” w SQL Server (i SQL Edge)

  2. Zapytanie SQL, aby znaleźć N-tą najwyższą pensję z tabeli wynagrodzeń

  3. varbinary do ciągu w SQL Server

  4. Składnia pętli for w SQL Server

  5. Profilowanie zapytań 101 — tak, naprawdę może poprawić wydajność serwera SQL