在分组/聚合期间连接/合并数组值

Yan*_* K. 23 sql postgresql

我有一个数组列类型的表:

 title       tags
"ridealong";"{comedy,other}"
"ridealong";"{comedy,tragedy}"
"freddyjason";"{horror,silliness}"
Run Code Online (Sandbox Code Playgroud)

我想编写一个查询,每个标题生成一个数组(理想情况下,它将是一个set/deduplicated数组)

例如

select array_cat(tags),title from my_test group by title
Run Code Online (Sandbox Code Playgroud)

上面的查询当然不起作用,但我想生成2行:

"ridealong";"{comedy,other,tragedy}"
"freddyjason";"{horror,silliness}"
Run Code Online (Sandbox Code Playgroud)

任何帮助或指针将非常感谢(我使用的是Postgres 9.1)


基于Craig的帮助,我最终得到了以下内容(自9.1以来,语法略有改变,完全按照他的说法抱怨查询)

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;
Run Code Online (Sandbox Code Playgroud)

Cra*_*ger 25

自定义聚合

方法1:定义自定义聚合.这是我之前写的.

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;
Run Code Online (Sandbox Code Playgroud)

LATERAL查询

...或者由于您不想保留订单并希望进行重复数据删除,您可以使用如下LATERAL查询:

SELECT title, array_agg(DISTINCT tag ORDER BY tag) 
FROM my_test, unnest(tags) tag 
GROUP BY title;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您不需要自定义聚合.由于重复数据删除,这对于大数据集来说可能要慢得多.但是,ORDER BY如果不需要,删除可能会有所帮助.

  • 从 Postgres-14 开始,AGGREGATE 定义必须使用 `anyknownarray` 而不是 `anyarray`。 (3认同)

poz*_*ozs 5

显而易见的解决方案是LATERAL连接(@CraigRinger 也建议这样做),但它已在 9.3 中添加到 PostgreSQL。

在 9.1 中,您无法避免子查询,但您可以简化它:

SELECT title, array_agg(DISTINCT tag)
FROM (SELECT title, unnest(tags) FROM my_test) AS t(title, tag)
GROUP BY title;
Run Code Online (Sandbox Code Playgroud)

SQL小提琴