PostgreSQL:在group by子句中连接数组

tbz*_*tbz 6 sql arrays postgresql group-by postgresql-9.1

我们有一个问题将数组分组到一个数组中.我们希望将两个列中的值连接到一个单独的数组中,并聚合这些多行的数组.

鉴于以下输入:

| id | name | col_1 | col_2 |
| 1  |  a   |   1   |   2   |
| 2  |  a   |   3   |   4   |
| 4  |  b   |   7   |   8   |
| 3  |  b   |   5   |   6   |
Run Code Online (Sandbox Code Playgroud)

我们想要以下输出:

| a | { 1, 2, 3, 4 } |
| b | { 5, 6, 7, 8 } |
Run Code Online (Sandbox Code Playgroud)

元素的顺序很重要,应该与聚合行的id相关联.

我们尝试了array_agg函数:

SELECT array_agg(ARRAY[col_1, col_2]) FROM mytable GROUP BY name;
Run Code Online (Sandbox Code Playgroud)

不幸的是,这句话引发了一个错误:

ERROR: could not find array type for data type character varying[]
Run Code Online (Sandbox Code Playgroud)

似乎不可能使用array_agg在group by子句中合并数组.

有任何想法吗?

Erw*_*ter 6

UNION ALL

你可以先用"反转" UNION ALL:

SELECT name, array_agg(c) AS c_arr
FROM  (
   SELECT name, id, 1 AS rnk, col1 AS c FROM tbl
   UNION ALL
   SELECT name, id, 2, col2 FROM tbl
   ORDER  BY name, id, rnk
   ) sub
GROUP  BY 1;
Run Code Online (Sandbox Code Playgroud)

适合生成您稍后请求的值的顺序.每个文件:

集合函数array_agg,json_agg,string_agg,和xmlagg,以及类似用户定义集合函数,产生依赖于输入值的顺序上有意义不同的结果值.默认情况下,此排序未指定,但可以通过ORDER BY在聚合调用中编写子句来控制,如第4.2.7节所示.或者,从排序的子查询中提供输入值通常会起作用.

自定义聚合函数

或者你可以创建一个自定义聚合函数,就像在这些相关答案中讨论的那样:
在Postgres数组中选择数据在PostgreSQL中
是否有类似两个数组的zip()函数?

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
   ,STYPE     = anyarray
   ,INITCOND  = '{}'
);
Run Code Online (Sandbox Code Playgroud)

然后你可以:

SELECT name, array_agg_mult(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM   tbl
GROUP  BY 1
ORDER  BY 1;
Run Code Online (Sandbox Code Playgroud)

或者,通常更快,而不是SQL标准:

SELECT name, array_agg_mult(ARRAY[col1, col2]) AS c_arr
FROM  (SELECT * FROM tbl ORDER BY name, id) t
GROUP  BY 1;
Run Code Online (Sandbox Code Playgroud)

添加的ORDER BY id(可以附加到这样的聚合函数)保证您期望的结果:

{1,2,3,4}
{5,6,7,8}
Run Code Online (Sandbox Code Playgroud)

或者您可能对此替代方案感兴趣:

SELECT name, array_agg_mult(ARRAY[ARRAY[col1, col2]] ORDER BY id) AS c_arr
FROM   tbl
GROUP  BY 1
ORDER  BY 1;
Run Code Online (Sandbox Code Playgroud)

哪个产生二维数组:

{{1,2},{3,4}}
{{5,6},{7,8}}
Run Code Online (Sandbox Code Playgroud)