gpt4 book ai didi

sql - 在 group by 子句中连接数组

转载 作者:行者123 更新时间:2023-11-29 11:24:23 25 4
gpt4 key购买 nike

我们在将数组分组为单个数组时遇到了问题。我们想将两列的值连接到一个数组中,然后聚合这些多行数组。

给定以下输入:

| id | name | col_1 | col_2 |
| 1 | a | 1 | 2 |
| 2 | a | 3 | 4 |
| 4 | b | 7 | 8 |
| 3 | b | 5 | 6 |

我们想要以下输出:

| a | { 1, 2, 3, 4 } |
| b | { 5, 6, 7, 8 } |

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

我们尝试了 array_agg() 函数:

SELECT array_agg(ARRAY[col_1, col_2]) FROM mytable GROUP BY name;

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

ERROR: could not find array type for data type character varying[]

似乎不可能使用 array_agg() 将数组合并到一个 group by 子句中。

有什么想法吗?

最佳答案

联合所有

您可以先使用 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;

适用于生成您稍后请求的值的顺序。 The manual:

The aggregate functions array_agg, json_agg, string_agg, and xmlagg,as well as similar user-defined aggregate functions, producemeaningfully different result values depending on the order of theinput values. This ordering is unspecified by default, but can becontrolled by writing an ORDER BY clause within the aggregate call, asshown in Section 4.2.7. Alternatively, supplying the input values froma sorted subquery will usually work.

大胆强调我的。

LATERAL subquery使用 VALUES 表达式

LATERAL 需要 Postgres 9.3 或更高版本。

SELECT t.name, array_agg(c) AS c_arr
FROM (SELECT * FROM tbl ORDER BY name, id) t
CROSS JOIN LATERAL (VALUES (t.col1), (t.col2)) v(c)
GROUP BY 1;

同样的结果。只需要在 table 上走一遍。

自定义聚合函数

或者您可以创建自定义聚合函数,就像这些相关答案中讨论的那样:

CREATE AGGREGATE array_agg_mult (anyarray)  (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);

然后你可以:

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

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

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

添加的 ORDER BY id(可以附加到此类聚合函数)保证您想要的结果:

a | {1,2,3,4}
b | {5,6,7,8}

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

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

生成二维数组:

a | {{1,2},{3,4}}
b | {{5,6},{7,8}}

最后一个可以用 Postgres 9.5 或更高版本中的内置 array_agg() 替换(并且应该替换,因为它更快!) - 添加聚合数组的能力:

SELECT name, array_agg(ARRAY[col1, col2] ORDER BY id) AS c_arr
FROM tbl
GROUP BY 1
ORDER BY 1;

同样的结果。 The manual:

input arrays concatenated into array of one higher dimension (inputsmust all have same dimensionality, and cannot be empty or null)

所以和我们自定义的聚合函数array_agg_mult()不完全一样;

关于sql - 在 group by 子句中连接数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24557344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com