【发布时间】:2020-07-30 20:45:29
【问题描述】:
考虑一个用于获取一组数组的集合并集的自定义聚合:
CREATE FUNCTION array_union_step (s ANYARRAY, n ANYARRAY) RETURNS ANYARRAY
AS $$ SELECT s || n; $$
LANGUAGE SQL IMMUTABLE LEAKPROOF PARALLEL SAFE;
CREATE FUNCTION array_union_final (s ANYARRAY) RETURNS ANYARRAY
AS $$
SELECT array_agg(i ORDER BY i) FROM (
SELECT DISTINCT UNNEST(x) AS i FROM (VALUES(s)) AS v(x)
) AS w WHERE i IS NOT NULL;
$$
LANGUAGE SQL IMMUTABLE LEAKPROOF PARALLEL SAFE;
CREATE AGGREGATE array_union (ANYARRAY) (
SFUNC = array_union_step,
STYPE = ANYARRAY,
FINALFUNC = array_union_final,
INITCOND = '{}',
PARALLEL = SAFE
);
据我了解,PostgreSQL 中的数组连接将两个输入的所有元素复制到一个新数组中,因此这是元素总数的二次方(在重复数据删除之前)。如果不用 C 语言编写扩展代码,是否有更有效的替代方案? (具体来说,使用 LANGUAGE SQL 或 LANGUAGE plpgsql。)例如,step 函数可能会以某种方式获取并返回一组行?
需要能够处理的数据类型示例:
create temp table demo (tag int, values text[]);
insert into demo values
(1, '{"a", "b"}'),
(2, '{"c", "d"}'),
(1, '{"a"}'),
(2, '{"c", "e", "f"}');
select tag, array_union(values) from demo group by tag;
tag | array_union
-----+-------------
2 | {c,d,e,f}
1 | {a,b}
请特别注意,内置的array_agg不能与这些数据一起使用,因为数组的长度不同:
select tag, array_agg(values) from demo group by tag;
ERROR: cannot accumulate arrays of different dimensionality
【问题讨论】:
标签: postgresql aggregate-functions plpgsql