SQL Server

Spojení řetězců pomocí FOR XML PATH

Spojení textových řetězců z více sloupců na řádek můžeme v SQL Serveru v edicích 2016 a nižších vyřešit pomocí FOR XML PATH a je to i vůbec nejpoužívanější způsob. V SQL Serveru 2017 dosáhneme stejného výsledku mnohem elegantnější cestou pomocí funkce STRING_AGG(), která ve všem plně nahradí FOR XML PATH.

Na následujících příkladech si ukážeme, jak na to. Naplníme si testovací tabulku jednoduchými řetězci, které spojíme dohromady pomocí FOX XML PATH. V příkladu vidíme dva možné zápisy: se specifikací datových typů a zjednodušený:

CREATE TABLE dbo.SampleTable
(
    Value VARCHAR(100)
)
GO

INSERT INTO dbo.SampleTable
        ( Value )
    SELECT 'Value1' UNION ALL
    SELECT 'Value2' UNION ALL
    SELECT 'Value3' UNION ALL
    SELECT 'Value4'
GO

SELECT STUFF((SELECT ',' AS "text()", '''' AS "text()", Value AS "text()",  '''' AS "text()"
                 FROM dbo.SampleTable
                 FOR XML PATH(''))
             , 1, 1, '')
GO

-- returns: 'Value1','Value2','Value3','Value4'

SELECT STUFF((SELECT ','  + '''' + Value + '''' FROM dbo.SampleTable FOR XML PATH('')), 1, 1, '')
GO

-- returns: 'Value1','Value2','Value3','Value4'

V dalším příkladu vidíme použití stejné metody v rámci datového setu, kdy agregujeme názvy měst pro jednotlivé státy:

-- create sample tables
CREATE TABLE dbo.tblCountry
(
    Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    Name VARCHAR(100) NOT NULL
)

CREATE TABLE dbo.tblCity
(
    Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    CountryId INT NOT NULL,
    NAME VARCHAR(100) NOT NULL
)    

-- populate data
ALTER TABLE dbo.tblCity ADD CONSTRAINT FK_tblCity_tblCity FOREIGN KEY (CountryId) 
    REFERENCES dbo.tblCity (Id)

INSERT INTO dbo.tblCountry
    VALUES ('Germany'), ('Czech Republic')

INSERT INTO dbo.tblCity
    VALUES (1, 'Bonn'), (1, 'Berlin')

INSERT INTO dbo.tblCity
    VALUES (2, 'Praha'), (2, 'Brno'), (2, 'Ostrava')

-- review data
SELECT *
FROM dbo.tblCountry country
    INNER JOIN dbo.tblCity city ON city.CountryId = country.Id

CSVListOfValuesInsideColumn1

-- put cities to inline CSV format
SELECT *
FROM dbo.tblCountry country
    CROSS APPLY (SELECT stuff((SELECT ', ' + c.Name 
                 FROM dbo.tblCity c 
                 WHERE c.CountryId = country.Id
                 FOR XML PATH('')), 1,2,'') Cities
                 FROM (SELECT 1 ID) a) city

CSVListOfValuesInsideColumn2

Leave a Reply

Your email address will not be published. Required fields are marked *