2010-09-30 18 views
11

Ho una tabella come questa per salvare i risultati di un controllo medico e la data del rapporto inviato e il risultato. In realtà la data di invio è basata sulla data di clinic_visit. Un cliente può avere uno o più rapporti (la data può variare)PostgreSQL: come combinare più righe?

--------------------------------------- 
| client_id | date_sent | result | 
--------------------------------------- 
| 1   | 2001  | A | 
| 1   | 2002  | B | 
| 2   | 2002  | D | 
| 3   | 2001  | A | 
| 3   | 2003  | C | 
| 3   | 2005  | E | 
| 4   | 2002  | D | 
| 4   | 2004  | E | 
| 5   | 2004  | B | 
--------------------------------------- 

Desidero estrarre il seguente rapporto dai dati di cui sopra.

--------------------------------------------------- 
| client_id | result1 | result2 | resut3 | 
--------------------------------------------------- 
|  1  | A  | B  |   | 
|  2  | D  |   |   | 
|  3  | A  | C  |  E  | 
|  4  | D  | E  |   | 
|  5  | B  |   |   | 
--------------------------------------------------- 

Sto lavorando su Postgresql. la funzione "crosstab" non funzionerà qui perché "date_sent" non è coerente per ogni client.

Qualcuno può dare un'idea approssimativa di come dovrebbe essere richiesto?

risposta

14

suggerisco il seguente approccio:

SELECT client_id, array_agg(result) AS results 
    FROM labresults 
    GROUP BY client_id; 

non è esattamente lo stesso formato di output, ma vi darà le stesse informazioni molto più veloce e più pulito.

Se si desidera che i risultati in colonne separate, si può sempre fare questo:

SELECT client_id, 
     results[1] AS result1, 
     results[2] AS result2, 
     results[3] AS result3 
FROM 
(
    SELECT client_id, array_agg(result) AS results 
     FROM labresults 
     GROUP BY client_id 
) AS r 
ORDER BY client_id; 

anche se questo sarà ovviamente introdurre una serie hardcoded di possibili risultati.

+0

La soluzione funziona, ma penso che l'OP desideri che i dati siano tabulati come nella domanda, in modo che sia facile vedere dove sono le voci vuote (il client 1 non ha alcun risultato E per esempio). – SabreWolfy

+2

@SabreWolfy: aggiornato –

+3

Questa risposta risolve il problema e dovrebbe essere accettata dall'OP. – SabreWolfy

0

Mentre leggevo su "simulating row_number", ho cercato di capire un altro modo per farlo.

SELECT client_id, 
     MAX(CASE seq WHEN 1 THEN result ELSE '' END) AS result1, 
     MAX(CASE seq WHEN 2 THEN result ELSE '' END) AS result2, 
     MAX(CASE seq WHEN 3 THEN result ELSE '' END) AS result3, 
     MAX(CASE seq WHEN 4 THEN result ELSE '' END) AS result4, 
     MAX(CASE seq WHEN 5 THEN result ELSE '' END) AS result5 
FROM (SELECT p1.client_id, 
       p1.result, 
       (SELECT COUNT(*) 
       FROM labresults p2 
       WHERE p2.client_id = p1.client_id 
       AND p2.result <= p1.result) 
     FROM labresults p1 
) D (client_id, result, seq) 
GROUP BY client_id; 

ma la query ha richiesto 10 minuti (500.000 ms ++). per 30.000 record. Questo è troppo lungo ..

+0

Utilizzare EXPLAIN ANALAYZE per vedere come viene eseguita la query e quali indici vengono utilizzati. client_id ha bisogno di un indice. –

+0

Grazie Frank .. Ho indicizzato il "client_id" e ora viene eseguito in meno di 5000 ms. – thinzar00

+2

Con Postgres non è necessario "simulare" il numero_riga. Questa funzione è disponibile a partire dall'8,4 (e se si sta utilizzando una versione precedente, si consiglia vivamente di eseguire l'aggiornamento il prima possibile) –

Problemi correlati