Affichage des articles dont le libellé est lignes et colonne. Afficher tous les articles
Affichage des articles dont le libellé est lignes et colonne. Afficher tous les articles

12 décembre 2018

SQL - Concaténer plusieurs lignes dans une colonne

Ça arrive de temps en en temps : j'ai besoin de remonter dans une colonne une liste de pleins d'éléments présent dans plusieurs lignes d'une sous table.

Pour être concret :
On a une table activité : dbo.activite qui contient les colonnes: actId; actNom
On a une table participant d'une activité : dbo.participant qui contient les colonnes : parId, parNom, actId

J'ai besoin de remonter sur une ligne les activités avec une colonne contenant les noms de tous les participants de chaque activité !

Ma proposition :
SELECT a.actId, a.actNom
, (SELECT p.parNom + ', ' as [text()] 
   FROM dbo.participant p 
   WHERE p.actId = a.actId 
   ORDER BY p.parId 
   FOR XML PATH('')) AS participants
FROM dbo.activite a 

Cette requête remonte les infos de la table activité et une colonne participants qui contient les noms séparés par une virgule des participants de l'activité.

Les points à noter :
La colonne participants est construite par une sous requête qui remonte en XML (FOR XML PATH('')) les noms des participants en y ajoutant un séparateur (la virgule + espace ici),
Cette sous requête, remontée dans une colonne de résultat, a pour effet de concaténer les lignes de XML en une seule valeur.
La colonne remontée est renommée AS [text()], fonction de conversion XML qui permet à SQL Server de retirer les balises XML ! (Tout est la !!) . Cela nettoie la chaîne concaténée des balises xml inutiles ici (Attention text() est sensible à la casse : il doit être écrit en minuscule, n'oubliez pas non plus les parenthèses pour que la méthode soit invoquée, le tout entre crochet ou apostrophes pour respecter la syntaxe SQL ).

A noter la clause Order By qui s'assure de l'ordre de présentation des participants.

Reste un petite erreur dans ce qui est remonté : La liste des noms se termine par un séparateur (la virgule + espace ici), il faudra filtrer cela dans l'applicatif ou complexifier la requête pour retirer les 2 derniers caractères inutiles.


Maj 05/2021 : Attention aussi au contenu remonté, s'il y a des caractères spéciaux (pour l'XML) ils seront XML encodé, il faudra donc les décoder avant de les utiliser. Avec par exemple CONVERT(NVARCHAR(MAX), CONVERT(XML, participants)dans l'exemple ci dessus.
 

 

Enjoy !