相当于PostgreSQL GROUP_CONCAT?


247

我有一张桌子,我想将每个ID与连接的字段值连接成一行。

例如,在我的表格中,我有这个:

TM67 | 4  | 32556
TM67 | 9  | 98200
TM67 | 72 | 22300
TM99 | 2  | 23009
TM99 | 3  | 11200

我想输出:

TM67 | 4,9,72 | 32556,98200,22300
TM99 | 2,3    | 23009,11200

在MySQL中,我能够使用聚合函数GROUP_CONCAT,但是在这里似乎不起作用... PostgreSQL是否具有等效功能,或者还有另一种方法可以实现此目的?





1
我认为最好的答案仍然是另一个问题:stackoverflow.com/a/47638417/243233
Jus12

Answers:


237

这可能是一个很好的起点(仅限8.4+版本):

SELECT id_field, array_agg(value_field1), array_agg(value_field2)
FROM data_table
GROUP BY id_field

array_agg返回一个数组,但是您可以使用CAST将该文本进行文本化和编辑(请参见下面的说明)。

在8.4版之前,必须在使用前自行定义:

CREATE AGGREGATE array_agg (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);

(摘自PostgreSQL文档)

说明:

  • 将数组强制转换为文本的结果是,结果字符串以大括号开头和结尾。如果不需要,则需要通过某些方法将其除去。
  • 将ANYARRAY转换为TEXT可以最好地模拟CSV输出,因为包含嵌入逗号的元素会在输出中以标准CSV样式加双引号。array_to_string()或string_agg()(在9.1中添加了“ group_concat”函数)都没有引用带有嵌入式逗号的字符串,从而导致结果列表中的元素数量不正确。
  • 新的9.1 string_agg()函数不会将内部结果首先转换为TEXT。因此,如果value_field为整数,则“ string_agg(value_field)”将生成错误。将需要“ string_agg(value_field :: text)”。array_agg()方法在聚合之后只需要进行一次强制转换(而不是按值强制转换)。

1
在9.0中,您将拥有listagg()
Scott Bailey 2010年

6
要获取CSV,查询应为:SELECT id_field,array_to_string(array_agg(value_field1),','),array_to_string(array_agg(value_field2),',')FROM data_table GROUP BY id_field
Nux 2012年

2
您不能在所有情况下都使用array_to_string。如果您的value_field包含嵌入式逗号,则结果CSV不正确。使用array_agg()并强制转换为TEXT会正确引用带有嵌入式逗号的字符串。唯一需要注意的是,它还包括开始和结束花括号,因此我的声明“并根据需要进行编辑”。我将进行编辑以澄清这一点。
马修·伍德

仅供参考:这是8.4中array_agg文档
Michael Rusch

255

从9.0开始,这变得更加容易:

SELECT id, 
       string_agg(some_column, ',')
FROM the_table
GROUP BY id

32
注意语法也允许你在字符串中指定值的顺序(或阵列,使用array_agg),例如string_agg(some_column, ',' ORDER BY some_column),甚至string_agg(surname || ', ' || forename, '; ' ORDER BY surname, forename)
IMSOP

8
这真棒该distinct作品与string_agg,因此可以使用string_agg(distinct some_solumn, ',')
阿伦

3
请注意,TEXT如果列值为不可字符串化的值(即uuid),则可能需要将其强制转换为。这看起来像string_agg(some_column::text, ',')
Kendall

48
SELECT array_to_string(array(SELECT a FROM b),', ');

也会做的。


是否可以执行此注释中的操作(按特定顺序汇总)?您将如何处理按一列分组和按另一列分组的顺序(例如,将纵向数据集中的变量连接起来)?
Michael A

15

尝试这样:

select field1, array_to_string(array_agg(field2), ',')
from table1
group by field1;

2

以及适用于数组类型的版本:

select
  array_to_string(
    array(select distinct unnest(zip_codes) from table),
    ', '
);

重复的答案,@ max_spy在五年前说过同样的话
EmilVikström19年

@EmilVikström:您有权错,但请仔细阅读。这不仅有所不同,而且我举了一个示例,该示例适用于数组类型,例如zip_codes是character varying(5)[]。另外,我已经验证了这样做的目的-不需要嵌套,否则您将看到ERROR: cannot accumulate arrays of different dimensionality
斯瓦沃米尔Lenart

1

我对PostgreSQL的建议

SELECT cpf || ';' || nome || ';' || telefone  
FROM (
      SELECT cpf
            ,nome
            ,STRING_AGG(CONCAT_WS( ';' , DDD_1, TELEFONE_1),';') AS telefone 
      FROM (
            SELECT DISTINCT * 
            FROM temp_bd 
            ORDER BY cpf DESC ) AS y
      GROUP BY 1,2 ) AS x   

1
为什么要进行ORDER BY内部查询?反正订单不会丢失吗?
mypetlion

-1

希望下面的Oracle查询能够正常工作。

Select First_column,LISTAGG(second_column,',') 
    WITHIN GROUP (ORDER BY second_column) as Sec_column, 
    LISTAGG(third_column,',') 
    WITHIN GROUP (ORDER BY second_column) as thrd_column 
FROM tablename 
GROUP BY first_column

我在rextester.com/l/postgresql_online_compiler对其进行了测试,但无法正常工作:42883:函数listagg(text,unknown,text)不存在
Manuel Romeiro

Oracle具有与postgres不同的语法和功能。
赫尔曼·拉德克三世
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.