我的遗留数据库有几行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的函数?”。链接的问题说:“我们怎样才能做一些与群组相关的事情(没有定义新的功能)?”没有答案,也符合我的要求。
选择的答案是现货!谢天谢地,它在关闭之前得到了解答。
答案 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查询;)