Question

This question already has an answer here:

If I have a table like this:

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

How can I get a resultset like this:

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

I know this is really easy to do in MySQL using GROUP_CONCAT, but I need to be able to do it in MSSQL 2005

Thanks

(Duplicate of How to use GROUP BY to concatenate strings in SQL Server?)

Was it helpful?

Solution

For a clean and efficient solution you can create an user defined aggregate function, there is even an example that does just what you need.
You can then use it like any other aggregate function (with a standard query plan):

query plan

OTHER TIPS

This will do:

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

Often asked here.

The most efficient way is using the FOR XML PATH trick.

This just came to me as one possible solution. I have no idea as to performance, but I thought it would be an interesting way to solve the problem. I tested that it works in a simple situation (I didn't code to account for NULLs). Feel free to give it a test to see if it performs well for you.

The table that I used included an id (my_id). That could really be any column that is unique within the group (grp_id), so it could be a date column or whatever.

;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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top