消除postgres中重复的数组值

我有一个biginttypes的数组,我该如何删除该数组中的重复值?

例如: array[1234, 5343, 6353, 1234, 1234]

我应该得到array[1234, 5343, 6353, ...]

我testing了在postgres手册中的示例SELECT uniq(sort('{1,2,3,2,1}'::int[])) ,但它不工作。

sort(int[])uniq(int[])函数由intarray contrib模块提供。

要启用它,你必须通过执行你可以在postgresql安装的contrib目录下find的_int.sql文件来注册这个模块。

在Debian / Ubuntu系统上,您必须安装postgresql-contrib-8.4软件包,那么文件将位于/usr/share/postgresql/8.4/contrib/_int.sql(版本号可能不同)

如果您不想使用intarray contrib模块,或者如果必须从不同types的数组中删除重复项,则可以使用其他两种方法。

如果你至less有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) 

或者,你可以创build自己的function来做到这一点

 CREATE OR REPLACE FUNCTION array_sort_unique (ANYARRAY) RETURNS ANYARRAY LANGUAGE SQL AS $body$ SELECT ARRAY( SELECT DISTINCT $1[si] 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) 

我面对同样的。 但在我的情况下数组是通过array_agg函数创build的。 幸运的是,它允许汇总DISTINCT值,如:

  array_agg(DISTINCT value) 

这对我有用。

我已经组装了一组存储过程(函数)来对抗PostgreSQL缺乏数组处理创造的arrays。 这些函数被devise用于跨任何数组数据types,而不仅仅是intarray中的整数: https ://www.github.com/JDBurnZ/anyarray

在你的情况下,你真正需要的是anyarray_uniq.sql 。 将该文件的内容复制并粘贴到PostgreSQL查询中并执行以添加该函数。 如果你需要数组sorting,也可以添加anyarray_sort.sql

从那里,你可以做一个简单的查询,如下所示:

SELECT ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234])

返回类似于: ARRAY[1234, 6353, 5343]

或者如果你需要sorting:

SELECT ANYARRAY_SORT(ANYARRAY_UNIQ(ARRAY[1234,5343,6353,1234,1234]))

返回: ARRAY[1234, 5343, 6353]

这是“内联”的方式:

 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; 

首先我们从数组中创build一个集合,然后我们只select不同的条目,然后将其聚合回数组中。

…这种array_X实用程序 标准 (?) 在哪里

尝试search…看到一些,但没有标准:

  • postgres.cz/wiki/Array_based_functions :很好的参考!

  • JDBurnZ / postgresql-anyarray ,很好的主动性,但需要一些协作来提高。

  • wiki.postgresql.org/Snippets ,挫败主动,但“offcial维基”,需要一些协作,以提高。

  • MADlib :好! ….但它是一个大象,而不是“纯粹的SQL片段库”。


最简单快速的array_distinct() snippet-lib函数

这里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; 

注意:它可以像任何数据types一样工作,除了数组数组,

 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}" 

“副作用”是分解一组元素中的所有数组。

PS:与JSONBarrays工作正常,

 SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] ); -- "{"[3, 3]","[5, 6]"}" 

编辑:更复杂但有用,一个“滴零”参数

 CREATE FUNCTION array_distinct( anyarray, -- input array boolean DEFAULT false -- flag to ignore nulls ) RETURNS anyarray AS $f$ SELECT array_agg(DISTINCT x) FROM unnest($1) t(x) WHERE CASE WHEN $2 THEN x IS NOT NULL ELSE true END; $f$ LANGUAGE SQL IMMUTABLE; 

对于像我这样的人,仍然需要处理postgres 8.2,这个recursion函数可以消除重复而不改变数组的sorting

 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} 

使用DISTINCT隐式sorting数组。 如果在删除重复项时需要保留数组元素的相对顺序 ,那么可以devise如下的函数:( 应该从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;