2009-06-02 14 views
10

Se ho una tabella come questa:gruppi CONCAT in SQL Server

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

Come posso ottenere un gruppo di risultati come questo:

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

So che questo è davvero facile da fare in MySQL utilizzando group_concat, ma ho bisogno di essere in grado di farlo in MSSQL 2005

Grazie

(Duplicate di 01.237.)

risposta

10

Per una soluzione pulita ed efficiente è possibile creare an user defined aggregate function, c'è anche an example che fa proprio quello che serve.
È quindi possibile utilizzarlo come qualsiasi altra funzione di aggregazione (con un piano di query standard):

query plan

+0

la soluzione più pulita ancora – Spyros

2

Spesso asked here.

Il modo più efficiente consiste nell'usare il trucco PER IL PERFETTO XML.

5

Questo farà:

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

Questo Inserto i valori in un documento XML, che è indesiderabile. – Boog

+4

No, utilizza le funzioni XML. Non ci sono documenti XML coinvolti. Perché è "indesiderabile"? –

1

Questo solo è venuto da me come una possibile soluzione. Non ho idea delle prestazioni, ma ho pensato che sarebbe stato un modo interessante per risolvere il problema. Ho provato che funziona in una situazione semplice (non ho codice per rendere conto di NULL). Sentiti libero di fare un test per vedere se si comporta bene per te.

La tabella che ho utilizzato ha incluso un ID (my_id). Potrebbe essere davvero una colonna unica nel gruppo (grp_id), quindi potrebbe essere una colonna di date o qualsiasi altra cosa.

;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