2009-06-02 10 views
10

Wenn ich habe eine Tabelle wie folgt aus:Concat Gruppen in SQL Server

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

Wie kann ich eine resultset wie diese:

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

Ich weiß, das ist wirklich einfach in MySQL zu tun mit GROUP_CONCAT, aber ich muss in der Lage sein, es

in MSSQL 2005

Dank zu tun

(Duplizieren von 01.237.)

Antwort

10

Für eine saubere und effiziente Lösung, die Sie an user defined aggregate function erstellen können, gibt es auch an example, dass genau das, was tut man braucht.
Sie können es dann wie jede andere Aggregatfunktion verwenden (mit einem Standard-Abfrage-Plan):

query plan

+0

die sauberste Lösung bisher – Spyros

2

Oft asked here.

Der effizienteste Weg ist die Verwendung des FOR XML PATH-Tricks.

5

wird dies tun:

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

Diese concats die Werte in einem XML-Dokument, was unerwünscht ist. – Boog

+4

Nein, es verwendet XML-Funktionen. Es sind keine XML-Dokumente vorhanden. Warum ist es "unerwünscht"? –

1

Dies ist für mich kam gerade als eine mögliche Lösung. Ich habe keine Ahnung von der Leistung, aber ich dachte, es wäre ein interessanter Weg, um das Problem zu lösen. Ich habe getestet, dass es in einer einfachen Situation funktioniert (ich habe nicht programmiert, um NULL zu berücksichtigen). Fühlen Sie sich frei, es zu testen, um zu sehen, ob es für Sie gut funktioniert.

Die Tabelle, die ich verwendete, enthielt eine ID (my_id). Das könnte wirklich jede Spalte sein, die in der Gruppe einzigartig ist (grp_id), also könnte es eine Datumsspalte sein oder was auch immer.

;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