sql >> Base de Datos >  >> RDS >> Sqlserver

Manera óptima de concatenar/agregar cadenas

SOLUCIÓN

La definición de óptimo puede variar, pero aquí se explica cómo concatenar cadenas de diferentes filas usando Transact SQL normal, que debería funcionar bien en 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

EXPLICACIÓN

El enfoque se reduce a tres pasos:

  1. Numere las filas usando OVER y PARTITION agrupándolos y ordenándolos según sea necesario para la concatenación. El resultado es Partitioned CTE. Mantenemos recuentos de filas en cada partición para filtrar los resultados más adelante.

  2. Usando CTE recursivo (Concatenated ) iterar a través de los números de fila (NameNumber columna) añadiendo Name valores a FullName columna.

  3. Filtre todos los resultados excepto los que tengan el NameNumber más alto .

Tenga en cuenta que para que esta consulta sea predecible, debe definir ambas agrupaciones (por ejemplo, en las filas de su escenario con el mismo ID están concatenados) y clasificación (supuse que simplemente ordenaría la cadena alfabéticamente antes de la concatenación).

Probé rápidamente la solución en SQL Server 2012 con los siguientes datos:

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

El resultado de la consulta:

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