Concatenate/merge array values during grouping/aggregation

匿名 (未验证) 提交于 2019-12-03 02:16:02

问题:

I have a table with the an array column type:

 title       tags "ridealong";"{comedy,other}" "ridealong";"{comedy,tragedy}" "freddyjason";"{horror,silliness}"

I would like to write a query that produces a single array per title(in an ideal world it would be a set/deduplicated array)

e.g.

select array_cat(tags),title from my_test group by title

The above query doesn't work of course, but I would like to produce 2 rows:

"ridealong";"{comedy,other,tragedy}" "freddyjason";"{horror,silliness}"

Any help or pointers would be very much appreciated (I am using Postgres 9.1)


Based on Craig's help I ended up with the following (slightly altered syntax since 9.1 complains about the query exactly as he shows it)

SELECT t1.title, array_agg(DISTINCT tag.tag)  FROM my_test t1, (select unnest(tags) as tag,title from my_test) as tag  where tag.title=t1.title GROUP BY t1.title;

回答1:

Custom aggregate

Approach 1: define a custom aggregate. Here's one I wrote earlier.

CREATE TABLE my_test(title text, tags text[]);  INSERT INTO my_test(title, tags) VALUES ('ridealong', '{comedy,other}'), ('ridealong', '{comedy,tragedy}'), ('freddyjason', '{horror,silliness}');  CREATE AGGREGATE array_cat_agg(anyarray) (   SFUNC=array_cat,   STYPE=anyarray );  select title, array_cat_agg(tags) from my_test group by title;

LATERAL query

... or since you don't want to preserve order and want to deduplicate, you could use a LATERAL query like:

SELECT title, array_agg(DISTINCT tag ORDER BY tag)  FROM my_test, unnest(tags) tag  GROUP BY title;

in which case you don't need the custom aggregate. This one is probably a fair bit slower for big data sets due to the deduplication. Removing the ORDER BY if not required may help, though.



回答2:

The obvious solution would be the LATERAL join (which also suggested by @CraigRinger), but that is added to PostgreSQL in 9.3.

In 9.1 you cannot avoid the sub-query, but you can simplify it:

SELECT title, array_agg(DISTINCT tag) FROM (SELECT title, unnest(tags) FROM my_test) AS t(title, tag) GROUP BY title;

SQL Fiddle



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!