SOLUTION
La définition de optimal peut varier, mais voici comment concaténer des chaînes de différentes lignes à l'aide de Transact SQL standard, ce qui devrait fonctionner correctement dans 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
EXPLICATION
L'approche se résume en trois étapes :
-
Numéroter les lignes en utilisant
OVER
etPARTITION
en les regroupant et en les ordonnant selon les besoins de la concaténation. Le résultat estPartitioned
CTE. Nous gardons le nombre de lignes dans chaque partition pour filtrer les résultats ultérieurement. -
Utilisation de CTE récursif (
Concatenated
) parcourir les numéros de ligne (NameNumber
colonne) en ajoutantName
valeurs àFullName
colonne. -
Filtrez tous les résultats sauf ceux avec le
NameNumber
le plus élevé .
Veuillez garder à l'esprit que pour rendre cette requête prévisible, il faut définir les deux regroupements (par exemple, dans vos lignes de scénario avec le même ID
sont concaténés) et le tri (j'ai supposé que vous triiez simplement la chaîne par ordre alphabétique avant la concaténation).
J'ai rapidement testé la solution sur SQL Server 2012 avec les données suivantes :
INSERT dbo.SourceTable (ID, Name)
VALUES
(1, 'Matt'),
(1, 'Rocks'),
(2, 'Stylus'),
(3, 'Foo'),
(3, 'Bar'),
(3, 'Baz')
Le résultat de la requête :
ID FullName
----------- ------------------------------
2 Stylus
3 Bar, Baz, Foo
1 Matt, Rocks