我在PostgreSQL中有两个我需要联合的数组。例如:
{1,2,3}
union {1,4,5}
将返回{1,2,3,4,5}
使用连接(||)运算符不会删除重复的条目,即返回{1,2,3,1,4,5}
我在网上找到了一个解决方案,但是我不喜欢它需要如何取消这两个数组:
select ARRAY(select unnest(ARRAY[1,2,3]) as a UNION select unnest(ARRAY[2,3,4,5]) as a)
是否有一个运算符或内置函数可以干净地结合两个数组?
答案 0 :(得分:17)
如果您的问题是不需要两次,那么只需要一次
select array_agg(a order by a)
from (
select distinct unnest(array[1,2,3] || array[2,3,4,5]) as a
) s;
答案 1 :(得分:10)
扩展intarray(在contrib包中)包含一些有用的函数和运算符:
postgres=# create extension intarray ;
CREATE EXTENSION
使用单管道操作员:
postgres=# select array[1,2,3] | array[3,4,5];
?column?
─────────────
{1,2,3,4,5}
(1 row)
或uniq
函数:
postgres=# select uniq(ARRAY[1,2,3] || ARRAY[3,4,5]);
uniq
─────────────
{1,2,3,4,5}
(1 row)
ANSI / SQL知道一个多集,但PostgreSQL还不支持它。
答案 2 :(得分:2)
可以这样做......
select uniq(sort(array_remove(array_cat(ARRAY[1,2,3], ARRAY[1,4,5]), NULL)))
给出:
{1,2,3,4,5}
需要array_remove,因为您无法使用NULLS对数组进行排序。
需要排序,因为uniq
仅在找到相邻元素时才重复删除。
这种方法相对于@Clodoaldo Neto的好处是,它在整个选择范围内起作用,并且不在FROM子句中排除。这使得在同一时间在单个表扫描中同时操作多个阵列列变得简单。 (虽然在评论中看到Ryan Guill版本的功能)。
此外,此模式适用于所有数组类型(谁的元素可排序)。
缺点是,可行的是,对于较长的数组,它的速度会慢一些(由于排序和3个中间数组分配)。
如果你想在结果中保留NULL,我认为这个和接受答案都会失败。
答案 3 :(得分:0)
当您尝试从行的 group 中获取数组值列的集合并集时,基于intarray
的答案不起作用。可以将接受的基于array_agg
的答案 修改为有效,例如
SELECT selector_column, array_agg(a ORDER BY a) AS array_valued_column
FROM (
SELECT DISTINCT selector_column, UNNEST(array_valued_column) AS a FROM table
) _ GROUP BY selector_column;
但是,如果将其深埋在复杂的查询中,则计划程序将无法将外部WHERE表达式传递过去,即使它们将大大减少必须处理的行数。在这种情况下,正确的解决方案是定义自定义聚合:
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
);
用法是
SELECT selector_column, array_union(array_valued_column) AS array_valued_column
FROM table
GROUP BY selector_column;
它在“内部”执行相同的操作,但是由于它被打包到一个聚合函数中,因此计划者可以看到它。
有可能通过让step函数执行UNNEST并将行附加到临时表(而不是临时数组)上来提高效率,但是我不知道该怎么做,这已经足够了我的用例。