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:
-
Numeruj wiersze za pomocą
OVER
iPARTITION
grupowanie i porządkowanie ich według potrzeb do konkatenacji. Wynik toPartitioned
CTE. Przechowujemy liczbę wierszy w każdej partycji, aby później filtrować wyniki. -
Używanie rekurencyjnego CTE (
Concatenated
) iteruj przez numery wierszy (NameNumber
kolumna) dodanieName
wartości doFullName
kolumna. -
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