我有一个bigint
类型的数组,如何删除该数组中的重复值?
例如:array[1234, 5343, 6353, 1234, 1234]
我应该array[1234, 5343, 6353, ...]
我在postgres手册中测试了示例SELECT uniq(sort('{1,2,3,2,1}'::int[]))
,但它无效。
答案 0 :(得分:65)
sort(int[])
和uniq(int[])
函数由intarray contrib模块提供。
要启用它,您必须通过执行postgresql安装的contrib目录中的_int.sql文件来注册模块。
在Debian / Ubuntu系统上你必须安装postgresql-contrib-8.4包,然后该文件将在/usr/share/postgresql/8.4/contrib/_int.sql下(版本号可能不同)
如果您不想使用intarray contrib模块,或者您必须从不同类型的数组中删除重复项,则还有其他两种方法。
如果您至少拥有PostgreSQL 8.4,则可以利用unnest(anyarray)
函数
SELECT ARRAY(SELECT DISTINCT UNNEST('{1,2,3,2,1}'::int[]) ORDER BY 1);
?column?
----------
{1,2,3}
(1 row)
或者您可以创建自己的功能来执行此操作
CREATE OR REPLACE FUNCTION array_sort_unique (ANYARRAY) RETURNS ANYARRAY
LANGUAGE SQL
AS $body$
SELECT ARRAY(
SELECT DISTINCT $1[s.i]
FROM generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
ORDER BY 1
);
$body$;
以下是一个示例调用:
SELECT array_sort_unique('{1,2,3,2,1}'::int[]);
array_sort_unique
-------------------
{1,2,3}
(1 row)
答案 1 :(得分:55)
我面对同样的事情。但我的案例中的数组是通过array_agg
函数创建的。幸运的是,它允许聚合 DISTINCT 值,例如:
array_agg(DISTINCT value)
这对我有用。
答案 2 :(得分:14)
... 此类 array_X实用程序的 statandard 库(?) ??
尝试搜索...查看一些但没有标准:
JDBurnZ/postgresql-anyarray,良好的主动性但需要一些合作来加强。
wiki.postgresql.org/Snippets,沮丧的倡议,但"官方维基",需要一些合作才能增强。
MADlib:好! ....但它是一个大象,而不是一个纯粹的SQL片段lib"。
array_distinct()
snippet-lib函数这是[{1}}或array_unique()
的最简单且可能更快的实现:
array_distinct()
注意:除了数组数组
之外,它可以按预期使用任何数据类型CREATE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x) FROM unnest($1) t(x);
$f$ LANGUAGE SQL IMMUTABLE;
"副作用"是爆炸一组元素中的所有数组。
PS:使用JSONB数组工作正常,
SELECT array_distinct( array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99] ),
array_distinct( array['3','3','hello','hello','bye'] ),
array_distinct( array[array[3,3],array[3,3],array[3,3],array[5,6]] );
-- "{1,2,3,4,6,8,99}", "{3,bye,hello}", "{3,5,6}"
编辑:更复杂但更有用," drop nulls"参数
SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] );
-- "{"[3, 3]","[5, 6]"}"
答案 3 :(得分:13)
我已经组装了一组存储过程(函数)来对抗PostgreSQL缺少数组处理创造的anyarray
。这些函数设计用于跨任何数组数据类型,而不仅仅是像inarray那样的整数:https://www.github.com/JDBurnZ/anyarray
在您的情况下,您真正需要的只是anyarray_uniq.sql
。复制&将该文件的内容粘贴到PostgreSQL查询中并执行它以添加该函数。如果您还需要数组排序,还可以添加anyarray_sort.sql
。
从那里,您可以执行如下简单查询:
SELECT ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234])
返回类似于:ARRAY[1234, 6353, 5343]
或者如果您需要排序:
SELECT ANYARRAY_SORT(ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234]))
完全返回:ARRAY[1234, 5343, 6353]
答案 4 :(得分:7)
这里是"内联"方式:
SELECT 1 AS anycolumn, (
SELECT array_agg(c1)
FROM (
SELECT DISTINCT c1
FROM (
SELECT unnest(ARRAY[1234,5343,6353,1234,1234]) AS c1
) AS t1
) AS t2
) AS the_array;
首先我们从数组创建一个集合,然后我们只选择不同的条目,然后将它聚合回数组。
答案 5 :(得分:5)
使用DISTINCT
隐式排序数组。如果在删除重复项时需要保留数组元素的相对顺序,则可以按如下方式设计该函数:(应该从9.4开始工作)
CREATE OR REPLACE FUNCTION array_uniq_stable(anyarray) RETURNS anyarray AS
$body$
SELECT
array_agg(distinct_value ORDER BY first_index)
FROM
(SELECT
value AS distinct_value,
min(index) AS first_index
FROM
unnest($1) WITH ORDINALITY AS input(value, index)
GROUP BY
value
) AS unique_input
;
$body$
LANGUAGE 'sql' IMMUTABLE STRICT;
答案 6 :(得分:4)
在一个查询中,我这样做:
SELECT (select array_agg(distinct val) from ( select unnest(:array_column) as val ) as u ) FROM :your_table;
答案 7 :(得分:2)
对于像我这样仍然需要处理postgres 8.2的人,这个递归函数可以消除重复,而不会改变数组的排序
CREATE OR REPLACE FUNCTION my_array_uniq(bigint[])
RETURNS bigint[] AS
$BODY$
DECLARE
n integer;
BEGIN
-- number of elements in the array
n = replace(split_part(array_dims($1),':',2),']','')::int;
IF n > 1 THEN
-- test if the last item belongs to the rest of the array
IF ($1)[1:n-1] @> ($1)[n:n] THEN
-- returns the result of the same function on the rest of the array
return my_array_uniq($1[1:n-1]);
ELSE
-- returns the result of the same function on the rest of the array plus the last element
return my_array_uniq($1[1:n-1]) || $1[n:n];
END IF;
ELSE
-- if array has only one item, returns the array
return $1;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
例如:
select my_array_uniq(array[3,3,8,2,6,6,2,3,4,1,1,6,2,2,3,99]);
将给出
{3,8,2,6,4,1,99}
答案 8 :(得分:-1)
可能的变体之一
UPDATE table SET array_column = uniq(array_column)