PostgreSQL array_agg排序

165

动物表:

animal_name animal_type
Tom         Cat
Jerry       Mouse
Kermit      Frog

查询:

SELECT 
array_to_string(array_agg(animal_name),';') animal_names,
array_to_string(array_agg(animal_type),';') animal_types
FROM animals;

期望的结果:

Tom;Jerry;Kerimt, Cat;Mouse;Frog
OR
Tom;Kerimt;Jerry, Cat;Frog;Mouse

我能确定第一个聚合函数中的顺序与第二个中的顺序始终相同吗?我的意思是我不想得到:

Tom;Jerry;Kermit, Frog;Mouse,Cat

8
如果您使用的是9.0版本,您可以将嵌套的函数调用替换为单个string_agg()函数。 - user330315
4个回答

464

使用ORDER BY,就像从手册中的以下示例:

SELECT array_agg(a ORDER BY b DESC) FROM table;

52
注意:array_agg中的ORDER BY在PostgreSQL 9中引入。 - UlfR
7
假设使用 PostgreSQL 9+,比接受的答案好得多。 - Erik
2
请问您能否提供一个带有 ORDER BY 的 SELECT 示例:SELECT array_agg(animal_name), array_agg(animal_type) FROM animals ORDER BY animal_name; - Grigory Kislin
17
请注意,这不适用于 array_agg(DISTINCT a ORDER BY b) - cerd
3
多列使用时需要添加括号:array_agg((a, b, c) ORDER BY b) - bennos
显示剩余6条评论

32

如果您使用的是 PostgreSQL 版本 < 9.0,则:

来源: http://www.postgresql.org/docs/8.4/static/functions-aggregate.html

在当前实现中,输入的顺序原则上是未指定的。然而,从排序子查询中提供输入值通常是可行的。例如:

SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;

���此,在您的情况下,您应该编写:

SELECT
array_to_string(array_agg(animal_name),';') animal_names,
array_to_string(array_agg(animal_type),';') animal_types
FROM (SELECT animal_name, animal_type FROM animals) AS x;

array_agg的输入将是无序的,但两列中的内容将相同。如果需要,可以在子查询中添加ORDER BY子句。


8

根据 Tom Lane 的说法:

... 如果我没看错的话,OP想要确保两个聚合函数在*同样未指定的顺序*下查看数据。 我认为这是一个非常安全的假设。 服务器必须费尽心思才能做出不同的事情,但它没有这样做。

... 因此,如果没有自己的ORDER BY,文档记录了聚合将以FROM子句提供的任何顺序查看行为预期的行为。

因此,我认为可以假设查询中所有不使用ORDER BY的聚合都将以相同的顺序查看输入数据。 顺序本身是未指定的(取决于FROM子句提供的行的顺序)。

来源:PostgreSQL邮件列表


1
这是唯一一个作者真正费心理解问题的答案,即“两个聚合体”是否具有相同的顺序。 - cantordust
1
我注意到,在邮件链中,Tom Lane明确建议不要为每个array_agg添加ORDER BY语句,原因是为了提高效率。 - Damien

2
做这个:
SELECT 
    array_to_string(array_agg(animal_name order by animal_name),';') animal_names,
    array_to_string(array_agg(animal_type order by animal_type),';') animal_types
FROM 
    animals;

但这会导致不同的顺序,具体取决于输入。 - cstork
这不是OP所问的,他希望将聚合结果排序以保持一致(animal_name1对应animal_type1)。 - Manuel Fedele

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接