2009-06-02 2 views
10

Если у меня есть таблица вроде этого:Concat группы в SQL Server

+------------+ 
| Id | Value | 
+------------+ 
| 1 | 'A' | 
|------------| 
| 1 | 'B' | 
|------------| 
| 2 | 'C' | 
+------------+ 

Как я могу получить ResultSet так:

+------------+ 
| Id | Value | 
+------------+ 
| 1 | 'AB' | 
|------------| 
| 2 | 'C' | 
+------------+ 

Я знаю, что это очень легко сделать в MySQL, используя GROUP_CONCAT, но мне нужно, чтобы быть в состоянии сделать это в MSSQL 2005

Благодаря

(дубликата How to use GROUP BY to concatenate strings in SQL Server?)

ответ

10

Для чистого и эффективного решения вы можете создать an user defined aggregate function, есть даже an example, что делает именно то, что вам нужно.
Вы можете использовать его как любую другую агрегатную функцию (с помощью стандартного плана запроса):

query plan

+0

самое чистое решение – Spyros

2

Часто asked here.

Наиболее эффективным способом является использование трюка FOR XML PATH.

5

Это будет делать:

SELECT mt.ID, 
     SUBSTRING((SELECT mt2.Value 
        FROM MyTable AS mt2 
        WHERE mt2.ID = mt.ID 
        ORDER BY mt2.VALUE 
        FOR XML PATH('')), 3, 2000) AS JoinedValue 
FROM MyTable AS mt 
+0

Это concats значения в документе XML, что является нежелательным. – Boog

+4

Нет, он использует функции XML. Документов XML нет. Почему это «нежелательно»? –

1

Это просто пришел ко мне, как одно из возможных решений. Я понятия не имею, что касается производительности, но я подумал, что это будет интересный способ решить проблему. Я тестировал, что он работает в простой ситуации (я не закодировал для учета NULL). Не стесняйтесь дать ему тест, чтобы убедиться, что он хорошо работает для вас.

В таблице, в которой я использовал, был включен id (my_id). Это действительно может быть любой столбец, который уникален внутри группы (grp_id), поэтому это может быть столбец даты или что-то еще.

;WITH CTE AS (
    SELECT 
     T1.my_id, 
     T1.grp_id, 
     CAST(T1.my_str AS VARCHAR) AS my_str 
    FROM 
     dbo.Test_Group_Concat T1 
    WHERE NOT EXISTS (SELECT * FROM dbo.Test_Group_Concat T2 WHERE T2.grp_id = T1.grp_id AND T2.my_id < T1.my_id) 
    UNION ALL 
    SELECT 
     T3.my_id, 
     T3.grp_id, 
     CAST(CTE.my_str + T3.my_str AS VARCHAR) 
    FROM 
     CTE 
    INNER JOIN dbo.Test_Group_Concat T3 ON 
     T3.grp_id = CTE.grp_id AND 
     T3.my_id > CTE.my_id 
    WHERE 
     NOT EXISTS (SELECT * FROM dbo.Test_Group_Concat T4 WHERE 
     T4.grp_id = CTE.grp_id AND 
     T4.my_id > CTE.my_id AND 
     T4.my_id < T3.my_id) 
) 
SELECT 
    CTE.grp_id, 
    CTE.my_str 
FROM 
    CTE 
INNER JOIN (SELECT grp_id, MAX(my_id) AS my_id FROM CTE GROUP BY grp_id) SQ ON 
    SQ.grp_id = CTE.grp_id AND 
    SQ.my_id = CTE.my_id 
ORDER BY 
    CTE.grp_id 
Смежные вопросы