2012-09-11 6 views
27

Sto usando PostgreSQL 9.1 e ho bisogno di aiuto per concatenare più righe in una. Ho bisogno di farlo in 2 tavoli. Quando uso due volte le funzioni array_agg() ottengo valori duplicati nel risultato.PostgreSQL 9.1: Come concatenare le righe nell'array senza duplicati, UNISCONA un'altra tabella

Tabelle:

CREATE TABLE rnp (id int, grp_id int, cabinets varchar(15)); 

INSERT INTO rnp VALUES 
(1,'11','cabs1') 
,(2,'11','cabs2') 
,(3,'11','cabs3') 
,(4,'11','cabs4') 
,(5,'22','c1') 
,(6,'22','c2'); 

CREATE TABLE ips (id int, grp_id int, address varchar(15)); 

INSERT INTO ips VALUES 
(1,'11','NY') 
,(2,'11','CA') 
,(3,'22','DC') 
,(4,'22','LA'); 

SQL:

SELECT DISTINCT 

    rnp.grp_id, 
    array_to_string(array_agg(rnp.cabinets)OVER (PARTITION BY rnp.grp_id), ',') AS cabinets, 
    array_to_string(array_agg(ips.address) OVER (PARTITION BY ips.grp_id), ',') AS addresses 


FROM rnp JOIN ips ON rnp.grp_id=ips.grp_id 

Risultato:

GRP_ID CABINETS            ADDRESSES 
11 cabs1,cabs1,cabs2,cabs2,cabs3,cabs3,cabs4,cabs4  NY,CA,NY,CA,NY,CA,NY,CA 
22 c1,c1,c2,c2            DC,LA,DC,LA 

E che cosa ho bisogno è:

GRP_ID  CABINETS     ADDRESSES 
    11 cabs1,cabs2,cabs3,cabs4  NY,CA, 
    22 c1,c2       DC,LA 

Questo esempio in SQLFiddle: http://sqlfiddle.com/#!1/4815e/19

Non v'è alcun problema se uso una tabella - SQLFiddle: http://sqlfiddle.com/#!1/4815e/20

Che cosa mi manca? È possibile farlo a causa di JOIN?

+3

Se potessi dare +5 buona domanda, lo farei. Versione specificata, dati di test, risultati attesi, query tentata. Ben fatto. –

+0

Grazie mille – lana80

risposta

28

Invece di utilizzare le funzioni delle finestre e patitioning, utilizzare un livello di query GROUP BY e aggregato con una clausola DISTINCT:

SELECT   
    rnp.grp_id, 
    array_to_string(array_agg(distinct rnp.cabinets),',') AS cabinets, 
    array_to_string(array_agg(distinct ips.address),',') AS addresses 
FROM rnp JOIN ips ON rnp.grp_id=ips.grp_id GROUP BY rnp.grp_id, ips.grp_id; 

Risultato:

grp_id |  cabinets   | addresses 
--------+-------------------------+----------- 
    11 | cabs1,cabs2,cabs3,cabs4 | CA,NY 
    22 | c1,c2     | DC,LA 
(2 rows) 

La chiave qui è che invece di utilizzare funzioni della finestra e patitioning, si utilizza un livello di query GROUP BY e si aggrega con una clausola DISTINCT.

This'd lavorare con l'approccio funzione finestra troppo, se non che PostgreSQL (9.1 almeno) non supporta DISTINCT a funzioni finestra:

regress=# SELECT DISTINCT 
    rnp.grp_id, 
    array_to_string(array_agg(distinct rnp.cabinets)OVER (PARTITION BY rnp.grp_id), ',') AS cabinets,      
    array_to_string(array_agg(distinct ips.address) OVER (PARTITION BY ips.grp_id), ',') AS addresses 
FROM rnp JOIN ips ON rnp.grp_id=ips.grp_id; 
ERROR: DISTINCT is not implemented for window functions 
LINE 3: array_to_string(array_agg(distinct rnp.cabinets)OVER (PART... 
+0

SI !!!! GRANDE!!!! Grazie mille! Ho perso un giorno intero a provare, e tu mi hai dato il risultato in un minuto! :) – lana80

+0

U ho ragione, ho provato a distinguere ma stavo ottenendo quell'errore !!! – lana80

+0

@ lana80 A volte ciò di cui hai bisogno è solo un nuovo paio di occhi quando hai osservato lo stesso problema tutto il giorno. Felice di aiutare. –