Объедините несколько строк с COALESCE - PullRequest
0 голосов
/ 20 ноября 2018

Использование SQL-Server 2012

У меня есть следующая таблица:

Id      Description 
6192    Salzburg
6193    Salzburg
6194    Salzburg
6196    Innsbruck
6197    Innsbruck
6198    Innsbruck
6199    Innsbruck
6201    Bregenz
6202    Bregenz
6203    Bregenz

Я хочу выбрать каждое отдельное «Описание» со всеми идентификаторами вместе в одной строке:

    Description     Ids
    Salzburg        '6192,6193,6194'
    Innsbruck       '6196,6197,6198'

Я видел похожий код на этом сайте [ Как объединить текст из нескольких строк в одну текстовую строку на SQL-сервере? , но я пока не мог понять его для своих целей(не хочу использовать XML Path!).Вот что я пробовал до сих пор:

DECLARE @ids AS Nvarchar(MAX)
SELECT  @ids = COALESCE(@ids + ',', '') + CAST(t.Id AS nvarchar(5))
    FROM (SELECT tmp.Id FROM (SELECT id, [Description] FROM tblMasterPropValues WHERE IdCategory = 253 AND IsActive = 1) as tmp
        WHERE [Description] = tmp.[Description]) AS t
SELECT @ids
--SELECT DISTINCT [Description], @ids AS IDs FROM tblMasterPropValues WHERE IdCategory = 253 AND IsActive = 1 AND Id IN (@ids)

Я не могу по-настоящему обдумать это и был бы признателен за любую помощь.

Ответы [ 4 ]

0 голосов
/ 20 ноября 2018

Вы также можете сделать это с помощью рекурсивного CTE

DECLARE @tblMasterPropValues TABLE (Id INT, Description VARCHAR(20))
INSERT INTO @tblMasterPropValues VALUES
(6192 , 'Salzburg'),
(6193 , 'Salzburg'),
(6194 , 'Salzburg'),
(6196 , 'Innsbruck'),
(6197 , 'Innsbruck'),
(6198 , 'Innsbruck'),
(6199 , 'Innsbruck'),
(6201 , 'Bregenz'),
(6202 , 'Bregenz'),
(6203 , 'Bregenz')



;WITH Tbl AS 
(
    SELECT 
        *, 
        ROW_NUMBER() OVER(PARTITION BY Description ORDER BY Id) AS RN,
        COUNT(*) OVER(PARTITION BY Description) AS CNT
    FROM @tblMasterPropValues 
)
, Rcr AS (
    SELECT *, CAST(Id AS varchar(max)) Ids 
    FROM Tbl WHERE RN = 1
        UNION ALL
    SELECT T.*, Rcr.Ids + ',' + CAST(T.Id AS VARCHAR(10)) Ids 
    FROM Rcr 
        INNER JOIN Tbl T ON T.RN = Rcr.RN + 1 and Rcr.Description = T.Description
)
SELECT RN, Description, Ids FROM Rcr 
WHERE RN = CNT

Результат:

Description          Ids
-------------------- -----------------------
Salzburg             6192,6193,6194
Innsbruck            6196,6197,6198,6199
Bregenz              6201,6202,6203
0 голосов
/ 20 ноября 2018

Для этого FOR XML PATH() является правильным предложением, поэтому вы можете сделать:

SELECT DISTINCT v.description, STUFF(v1.ids, 1, 1, '''') + '''' 
FROM tblMasterPropValues v CROSS APPLY
     (SELECT ', '+ CAST(v1.Id AS VARCHAR(255))
      FROM tblMasterPropValues v1
      WHERE v1.description = v.description 
      FOR XML PATH('')
     ) v1(ids);
0 голосов
/ 20 ноября 2018

Попробуйте:

DECLARE @Table TABLE(ID INT, Description VARCHAR(25))
INSERT INTO @Table
VALUES (6192,'Salzburg' )
,(6193,'Salzburg' )
,(6194,'Salzburg' )
,(6196,'Innsbruck')
,(6197,'Innsbruck')
,(6198,'Innsbruck')
,(6199,'Innsbruck')
,(6201,'Bregenz'     )
,(6202,'Bregenz'     )
,(6203,'Bregenz'     )

Запрос:

SELECT DISTINCT T2.Description, 
    SUBSTRING(
        (
            SELECT ','+CAST(T1.ID AS VARCHAR)  AS [text()]
            FROM @Table T1
            WHERE T1.Description = T2.Description
            ORDER BY T1.Description
            FOR XML PATH ('')
        ), 2, 1000) [Ids]
FROM @Table T2

Результат:

Description Ids
Bregenz     6201,6202,6203
Innsbruck   6196,6197,6198,6199
Salzburg    6192,6193,6194
0 голосов
/ 20 ноября 2018

Вы можете попробовать использовать STUFF() функцию

SELECT description,  Ids = STUFF(
             (SELECT ',' + Id
              FROM tblMasterPropValues t1
              WHERE t1.description = t2.description
              FOR XML PATH (''))
             , 1, 1, '') from tblMasterPropValues t2
group by description;
...