2010-01-12 15 views
65

Sto tentando di unire qualcosa di simile nel mio database SQL Server:È possibile che Comma delimga più righe in una colonna?

[TicketID], [Person] 
T0001  Alice 
T0001  Bob 
T0002  Catherine 
T0002  Doug 
T0003  Elaine

In questa:

[TicketID], [People] 
T0001  Alice, Bob 
T0002  Catherine, Doug 
T0003  Elaine

Ho bisogno di fare questo in SQL Server e Oracle.

Ho trovato la funzione GROUP_CONCAT per MySQL che fa esattamente ciò di cui ho bisogno qui, ma MySQL non è un'opzione qui.

EDIT: Banco di prova:

DECLARE @Tickets TABLE (
    [TicketID] char(5) NOT NULL, 
    [Person] nvarchar(15) NOT NULL 
) 

INSERT INTO @Tickets VALUES 
    ('T0001', 'Alice'), 
    ('T0001', 'Bob'), 
    ('T0002', 'Catherine'), 
    ('T0002', 'Doug'), 
    ('T0003', 'Elaine') 

SELECT * FROM @Tickets 

risposta

69

Ecco una soluzione che funziona in SQL Server 2005 +:

SELECT t.TicketID, 
     STUFF(ISNULL((SELECT ', ' + x.Person 
       FROM @Tickets x 
       WHERE x.TicketID = t.TicketID 
      GROUP BY x.Person 
      FOR XML PATH (''), TYPE).value('.','VARCHAR(max)'), ''), 1, 2, '') [No Preceeding Comma], 
     ISNULL((SELECT ', ' + x.Person 
       FROM @Tickets x 
       WHERE x.TicketID = t.TicketID 
      GROUP BY x.Person 
      FOR XML PATH (''), TYPE).value('.','VARCHAR(max)'), '') [Preceeding Comma If Not Empty] 
    FROM @Tickets t 
GROUP BY t.TicketID 

Riferimento:

+1

questo non funzionerà ... il gruppo che fai non usa il campo persone in modo che fallisca e il percorso xml non può prendere una virgola (,) come identificatore perché non può creare un elemento da esso .. –

+3

Bad-ass! Ti manca un gruppo in fondo, ma fantastico! –

+0

Sono curioso: è più veloce eseguire una query sul server o concatenare i risultati in memoria? – llamaoo7

10

ho trovato un modo per fare questo in Oracle, ma ho ancora bisogno di farlo in SQL Server.

Da http://technology.amis.nl/blog/6118/oracle-rdbms-11gr2-listagg-new-aggregation-operator-for-creating-comma-delimited-strings(Grazie tanging) (ORACLE 11 e fino)

select 
    TicketId, 
    listagg(Person, ', ') People 
from 
    table 
group by 
    TicketId 

Da: http://halisway.blogspot.com/2006/08/oracle-groupconcat-updated-again.html

with 
    data 
as 
    (
    select 
     TicketId, 
     Person, 
     ROW_NUMBER() over (partition by TicketId order by Person) "rownum", 
     COUNT(*) over (partition by TicketId) "count" 
    from 
     Table 
) 
select 
    TicketId, 
    LTRIM(sys_connect_by_path(Person,','),',') People 
from 
    data 
where 
    "rownum" = "count" 
start with 
    "rownum" = 1 
connect by 
    prior TicketId = TicketId 
    and 
    prior "rownum" = "rownum" - 1 
order by 
    TicketId 
+0

+1: Complimenti per l'esempio Oracle. Ci sono un paio di modi per farlo in Oracle, ma alcuni includono l'uso di funzionalità non supportate. –

+1

So che è vecchio, ma se usi 11g hai ListAgg (che sembra essere MOLTO simile a MySQL Group_CONCAT): http://technology.amis.nl/blog/6118/oracle-rdbms-11gr2-listagg -nuovo-aggregatore-operatore-per-creazione-virgole delimitato da virgole e http://download.oracle.com/docs/cd/E11882_01/server.112/e10592/functions087.htm – Harrison

+0

@tanging: Fantastico! Sto modificando la mia risposta per riflettere questo! –

13

E, la versione di MySQL, per completezza:

select 
    TicketId, 
    GROUP_CONCAT(Person ORDER BY Person SEPARATOR ', ') People 
from 
    table 
group by 
    TicketId 
8

un esempio

SELECT DISTINCT 
    t.TicketID, 
    STUFF((SELECT ', ', i.Person as [text()] 
      FROM @Tickets i 
      WHERE i.TicketID = t.TicketID 
      FOR XML PATH ('')), 1, 2, '') as People 
FROM 
    @Tickets t 

......... o prova ..............

/* questo funziona quando ho usato questo per il mio tavolo e il credito va al mio manager che ROCCE! */

+0

Lascia una virgola finale. –

+1

Mi sono preso la libertà di fare di questa partita l'esempio. Questo funziona in modo SIGNIFICATAMENTE più veloce della precedente risposta migliore. –

+1

@JohnGietzen il miglioramento delle prestazioni non arriva senza un costo. Questo non funzionerà come previsto per i valori contenenti per esempio un '&'. –

11
DECLARE @Tickets TABLE (
    [TicketID] char(5) NOT NULL, 
    [Person] nvarchar(15) NOT NULL 
) 
INSERT INTO @Tickets VALUES 
    ('T0001', 'Alice'), 
    ('T0001', 'Bob'), 
    ('T0002', 'Catherine'), 
    ('T0002', 'Doug'), 
    ('T0003', 'Elaine') 

SELECT * FROM @Tickets 

Select [TicketID], 
STUFF((SELECT ',' + Person FROM @Tickets WHERE (
TicketID=Result.TicketID) FOR XML PATH ('')),1,1,'') AS BATCHNOLIST 
From @Tickets AS Result 
GROUP BY TicketID 
+0

Nel mio scenario "Persona" era di tipo Money, e questa soluzione si è rivelata più veloce e più accurata della soluzione "OMG Ponies". – Omar

+0

Confermato che funziona perfettamente - grazie mille! – wdanda

Problemi correlati