2009-06-02 54 views
10

Nếu tôi có một bảng như thế này:nhóm concat trong SQL Server

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

Làm thế nào tôi có thể nhận được một resultset như thế này:

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

Tôi biết điều này là thực sự dễ dàng để làm trong MySQL sử dụng GROUP_CONCAT, nhưng tôi cần để có thể làm điều đó trong MSSQL 2005

Cảm ơn

(Duplicate của 01.237.)

Trả lời

10

Đối với một giải pháp làm sạch và hiệu quả bạn có thể tạo an user defined aggregate function, thậm chí còn có an example mà không chỉ là những gì bạn cần.
Sau đó bạn có thể sử dụng nó giống như bất kỳ chức năng tổng hợp khác (với một kế hoạch truy vấn chuẩn):

query plan

+0

giải pháp sạch nhất – Spyros

2

Thường asked here.

Cách hiệu quả nhất là sử dụng thủ thuật FOR XML PATH.

5

này sẽ làm:

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

này concats các giá trị trong một tài liệu XML, mà là không mong muốn. – Boog

+4

Không, nó sử dụng các hàm XML. Không có tài liệu XML nào liên quan. Tại sao nó "không mong muốn"? –

1

này chỉ đến với tôi như một giải pháp khả thi. Tôi không có ý tưởng về hiệu suất, nhưng tôi nghĩ đó sẽ là một cách thú vị để giải quyết vấn đề. Tôi đã thử nghiệm rằng nó hoạt động trong một tình huống đơn giản (tôi đã không mã tài khoản cho NULL). Cảm thấy tự do để cho nó một thử nghiệm để xem nó hoạt động tốt cho bạn.

Bảng mà tôi đã sử dụng bao gồm id (my_id). Điều đó thực sự có thể là bất kỳ cột nào là duy nhất trong nhóm (grp_id), do đó, nó có thể là một cột ngày tháng hoặc bất cứ điều gì.

;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 
Các vấn đề liên quan