Postgresql GROUP_CONCAT 等效?

Posted

技术标签:

【中文标题】Postgresql GROUP_CONCAT 等效?【英文标题】:Postgresql GROUP_CONCAT equivalent? 【发布时间】:2011-02-03 09:27:12 【问题描述】:

我有一张表,我想为每个 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 是否有等效的方法,或其他方式来完成此操作?

【问题讨论】:

不是答案,但请查看postgresonline.com/journal/index.php?/archives/…。 ***.com/questions/1943433/… Simulating group_concat MySQL function in SQL Server?的可能重复 我觉得最好的答案还是在另一个问题中:***.com/a/47638417/243233 【参考方案1】:

Since 9.0这更简单:

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

【讨论】:

请注意,该语法还允许您指定字符串(或数组,使用array_agg)中值的顺序,例如string_agg(some_column, ',' ORDER BY some_column) 甚至 string_agg(surname || ', ' || forename, '; ' ORDER BY surname, forename) distinct 与 string_agg 一起工作真是太棒了,所以可以使用string_agg(distinct some_solumn, ',') 请注意,如果列值是非字符串值(即uuid),您可能需要将其转换为TEXT。这看起来像string_agg(some_column::text, ',') 如果列类型是整数,别忘了转换或者使用concat(column, '')进行隐式转换 PS,string_agg(value, ',') 只能在value 是字符串的情况下使用。例如,如果value 是整数,value 需要转换为字符串,如value::character varying【参考方案2】:

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

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

array_agg 返回一个数组,但您可以将其转换为文本并根据需要进行编辑(请参阅下面的说明)。

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() 方法只需要在聚合之后进行一次转换(而不是对每个值进行一次转换)。

【讨论】:

在 9.0 中你将拥有 listagg() 要获取 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 这里不能在所有情况下都使用array_to_string。如果您的 value_field 包含嵌入式逗号,则生成的 CSV 不正确。使用 array_agg() 并转换为 TEXT 正确引用嵌入逗号的字符串。唯一需要注意的是它还包括开始和结束的花括号,因此我的声明是“并根据需要进行编辑”。我将进行编辑以澄清这一点。 仅供参考:这是docs on array_agg in 8.4的链接【参考方案3】:
SELECT array_to_string(array(SELECT a FROM b),', ');

也会这样做。

【讨论】:

是否可以在this comment 中执行类似的操作,按特定顺序聚合?您将如何处理按一列分组并按另一列排序(例如,连接纵向数据集中的变量)?【参考方案4】:

试试这样:

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

【讨论】:

【参考方案5】:

假设your_table表有三列(name、id、value),查询是这样的:

  select name, 
         array_to_string(array_agg(id), ','), 
         array_to_string(array_agg(value), ',')
    from your_table
group by name
order by name
;

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

KI

【讨论】:

【参考方案6】:

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

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

【讨论】:

重复回答,@max_spy 五年前也说过同样的话 @EmilVikström:你有权犯错,但请仔细阅读。它不仅不同,而且我举了一个例子,它适用于数组类型——比如 zip_codes 是character varying(5)[]。另外,我已经验证了我的目的 - 需要 unnest,否则你会看到ERROR: cannot accumulate arrays of different dimensionality【参考方案7】:

我对 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   

【讨论】:

你为什么在内部查询中使用ORDER BY?订单不会丢失吗?【参考方案8】:

希望下面的 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: function listagg(text, unknown, text) 不存在 Oracle 的语法和功能与 postgres 不同。

以上是关于Postgresql GROUP_CONCAT 等效?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle的函数WM_CONCAT,在PostgreSQL中具有相同功能的函数名称是啥?

跨 PDO 驱动兼容 GROUP_CONCAT?

postgresql

PostgreSQL 中的连接属性

mysql 的group_concat方法

解决mysql中group_concat长度限制的方案