Jak połączyć teksty z kolumn z wielu rekordów w jeden długi napis rozdzielany przecinkami?

12-Cze-2011

Nierzadko w kolumnach tabel jest przechowywany napis, który należy „wyciągnąć” z tabeli i wyświetlić w postaci listy rozwijanej. W zależności od używanego oprogramowania, może się okazać, że napis pobrany z tabeli powinien zawierać wartości porozdzielane przecinkami lub średnikami lub też innym znakiem np. „|” (pipe).

Okazuje się, że z wykorzystaniem języka SQL to zadanie może być prostsze niż by się na początku mogło wydawać. Załóżmy, że chcemy stworzyć porozdzielaną przecinkami listę języków zawartych w tabeli sys.syslanguages. Skrótowa nazwa języka znajduje się w kolumnie alias, stąd zapytanie:

SELECT alias FROM sys.syslanguages

Zwraca listę języków w postaci jednokolumnowej tabeli

Rozważmy więc następujący kod:

DECLARE @Str NVARCHAR(MAX) ='';
SELECT @str=@Str+','+alias
FROM sys.syslanguages
SELECT @Str

Do zainicjowanej zmiennej @Str wpisujemy alias języka pobierany z kolejnych rekordów tabeli. Przepisywanie nazwy nie zamazuje poprzedniej zawartości zmiennej, ale dokleja kolejny alias języka oraz znak rozdzielający, w tym przypadku przecinek.

Oto wynik:

Jak widać pozostał jeszcze jeden problem. Na początku zwróconego napisu pojawia się przecinek. Aby się go pozbyć skopujemy od prawej strony wszystkie znaki oprócz tego pierwszego:

 DECLARE @Str NVARCHAR(MAX) ='';
 SELECT @str=@Str+','+alias
FROM sys.syslanguages
 SELECT RIGHT(@Str,LEN(@str)-1)

Teraz wynik jest już poprawny:

Jeżeli nie podoba ci się wycinanie z napisu znaków od prawej strony, możesz się też posłużyć następującymi rozwiązaniami:

DECLARE @Str NVARCHAR(MAX) ='';
 SELECT @str=@Str+alias+','
FROM sys.syslanguages
 SELECT LEFT(@Str,LEN(@str)-1)

 Lub

 DECLARE @Str NVARCHAR(MAX);
 SELECT @str=ISNULL(@Str+',','')+alias
FROM sys.syslanguages
 SELECT @Str

 W ostatnim przypadku korzystam z tego, że tym razem niezainicjowany napis @str na początku jest równy NULL, a co za tym idzie funkcja ISNULL(@str+’,’,’’) zwraca za pierwszym razem pusty napis. Przy każdym kolejnym rekordzie @str nie jest już NULL, więc ISNULL(@str+’,’,’’) zwraca @str+’,’

No i sprawa rozwiązana. Jeżeli interesuje cie jak odwrócić sytuację i z listy rozdzielanej przecinkami zrobić tabelę, to zapraszam do przeczytania artykułu na mobilo / mobilo24 o wykorzystaniu CTE, choć to już wyższa szkoła jazdy…

Tego rodzaju zagadnienia porusza też kurs Writing SQL Queries MS 2778. Zapraszam do bit Polska na autoryzowane kursy Microsoft w Opolu, Katowicach i Warszawie

Dodaj komentarz:

Autor: Rafał Kraik