Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
683 views
in Technique[技术] by (71.8m points)

sql - PostgreSQL 9.1: How to concatenate rows in array without duplicates, JOIN another table

I am using PostgreSQL 9.1 and need help with concatenating multiple rows in one. I need to do that in 2 tables. When I use two times array_agg() functions I get duplicated values in result.

Tables:

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

Result:

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

And what I need is:

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

This example in SQLFiddle: http://sqlfiddle.com/#!1/4815e/19

There is no problem if use one table - SQLFiddle: http://sqlfiddle.com/#!1/4815e/20

What am I missing? Is it possible to do this, because of JOIN?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Instead of using window functions and patitioning, use a query-level GROUP BY and aggregate with a DISTINCT clause:

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;

Result:

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

The key here is that instead of using window functions and patitioning, you use a query-level GROUP BY and aggregate with a DISTINCT clause.

This'd work with the window function approach too, except that PostgreSQL (9.1 at least) doesn't support DISTINCT in window functions:

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...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...