2017. január 26., csütörtök

SQL sorok összefűzése egy mezőbe FOR XML PATH segítségével


Ha az SQL-es táblában az értékek különböző sorokban vannak eltárolva, amit szeretnénk összefűzni egy mezőbe (pl. riporton helytakarékosság, felhasználóbarát formátum céljából), akkor arra több módszer is használható.

MySQL esetében erre külön függvény található: GROUP_CONCAT()
Oracle esetében: LISTAGG()
PostgreSQL esetében szintén van erre függvény: STRING_AGG()

Az MS SQL Server-en szokás szerint nincs ilyen egyszerű dolgunk. :) Az egyik leggyakoribb megoldás, amikor a FOR XML PATH-t használjuk.


1.   Ha egy táblán belül van az a mező, amire csoportosítani kell, és az a mező, amelynek értékeit össze kell fűznünk:

CREATE TABLE #Tabla
(
  Kategoria    varchar(20),
  Alkategoria varchar(20)
)

INSERT INTO #Tabla (Kategoria, Alkategoria) VALUES ('Kerékpár', 'verseny');
INSERT INTO #Tabla (Kategoria, Alkategoria) VALUES ('Kerékpár', 'túra');
INSERT INTO #Tabla (Kategoria, Alkategoria) VALUES ('Kerékpár', 'mountain bike');
INSERT INTO #Tabla (Kategoria, Alkategoria) VALUES ('Alkatrész', 'nyereg');
INSERT INTO #Tabla (Kategoria, Alkategoria) VALUES ('Alkatrész', 'pedál');

SELECT Kategoria,
       STUFF((SELECT ',' + t2.Alkategoria AS [text()] 
                FROM #Tabla t2 
               WHERE t2.Kategoria = t1.Kategoria 
                 FOR XML PATH('') ), 1, 1, '') Alkategoria
  FROM #Tabla t1
 GROUP BY Kategoria

DROP TABLE #Tabla



2.   Ha külön táblában vannak az összefűzendő értékek:

CREATE TABLE #Fej
(
  fej_id  int,
  fej_nev varchar(20)
)

INSERT INTO #Fej (fej_id, fej_nev) VALUES (1, 'Kerékpár');
INSERT INTO #Fej (fej_id, fej_nev) VALUES (2, 'Alkatrész');

CREATE TABLE #Tetel
(
  tetel_id  int,
  fej_id    int,
  tetel_nev varchar(20)
)

INSERT INTO #Tetel (tetel_id, fej_id, tetel_nev) VALUES (1, 1, 'verseny');
INSERT INTO #Tetel (tetel_id, fej_id, tetel_nev) VALUES (2, 1, 'túra');
INSERT INTO #Tetel (tetel_id, fej_id, tetel_nev) VALUES (3, 1, 'mountain bike');
INSERT INTO #Tetel (tetel_id, fej_id, tetel_nev) VALUES (4, 2, 'nyereg');
INSERT INTO #Tetel (tetel_id, fej_id, tetel_nev) VALUES (5, 2, 'pedál');

SELECT f.fej_nev,
       STUFF((SELECT ',' + t.tetel_nev [text()]
                FROM #Tetel t
               WHERE t.fej_id = f.fej_id
    FOR XML PATH('')  ), 1, 1, '' ) tetel_lista
  FROM #Fej f

DROP TABLE #Fej
DROP TABLE #Tetel