我们可以在PostgreSQL中定义GROUP_CONCAT函数吗?

时间:2017-12-04 16:21:07

标签: sql postgresql database-migration group-concat postgresql-9.4

我的遗留数据库有几行SQL代码和GROUP_CONCAT语句,如:

SELECT SUM(age), GROUP_CONCAT(sal) FROM Users;

在PostgreSQL中,我也可以这样做:

SELECT SUM(age), string_agg(sal, ', ') FROM Users;

我想尽可能多地重用旧的SQL。所以我需要定义一个内部调用GROUP_CONCAT的{​​{1}}函数。这可能吗?

编辑:链接的问题无关!

我的问题是“如何定义一个名为group_concat的函数?”。链接的问题说:“我们怎样才能做一些与群组相关的事情(没有定义新的功能)?”没有答案,也符合我的要求。

选择的答案是现货!谢天谢地,它在关闭之前得到了解答。

2 个答案:

答案 0 :(得分:2)

是的,这是可能的。看看它已经完成的https://github.com/2ndQuadrant/mysqlcompat/blob/master/sql_bits/aggregate.sql,如下:

-- GROUP_CONCAT()
-- Note: only supports the comma separator
-- Note: For DISTINCT and ORDER BY a subquery is required
CREATE OR REPLACE FUNCTION _group_concat(text, text)
RETURNS text AS $$
  SELECT CASE
    WHEN $2 IS NULL THEN $1
    WHEN $1 IS NULL THEN $2
    ELSE $1 operator(pg_catalog.||) ',' operator(pg_catalog.||) $2
  END
$$ IMMUTABLE LANGUAGE SQL;

CREATE AGGREGATE group_concat (
    BASETYPE = text,
    SFUNC = _group_concat,
    STYPE = text
);

答案 1 :(得分:2)

有一个内置的string_agg()可以执行您想要的操作,但您特别要求将其命名为group_concat以实现MySQL兼容性。不幸的是,string_agg()使用内部数据类型进行累积(可能是为了避免在每个附加上复制整个缓冲区,但我没有查看源代码)并且我没有找到一种方法来声明与string_agg相同的SQL aggrerate( )。

定义group_concat()函数也不起作用,因为必须让pg知道它是一个聚合,而不是一个隐藏在里面的聚合的函数,这是行不通的。这样的函数一次只能在一行上运行:里面的任何聚合只会聚合一行而不改变它...

因此,此代码将元素累积到数组中,然后使用array_to_string添加“,”分隔符。我将使用array_agg()声明(在它成为内置函数之前)作为模型,并简单地添加一个终结函数,它将聚合数组转换为文本。

guard 2+2 == 4 else {
print("The universe makes no sense")
return // this is mandatory!
}
print("We can continue with our daily lives")

好的一点是,它应该适用于任何类型,没有麻烦,这要归功于泛型类型“anyarray”和“anyelement”。

我认为如果string_agg确实避免在每个追加上复制整个聚合数组,那么这将比string_agg()慢。但是,只有当要分组到每个集合中的行数很大时,这才有意义。在这种情况下,您可能花一分钟编辑SQL查询;)

http://sqlfiddle.com/#!17/c452d/1