我有一个类型的数组bigint
,如何删除该数组中的重复值?
例如: array[1234, 5343, 6353, 1234, 1234]
我应该得到 array[1234, 5343, 6353, ...]
我SELECT uniq(sort('{1,2,3,2,1}'::int[]))
在postgres手册中测试了该示例,但是它不起作用。
Answers:
我面临着同样的事情。但是在我的情况下,数组是通过array_agg
函数创建的。幸运的是,它允许聚合DISTINCT值,例如:
array_agg(DISTINCT value)
这对我有用。
trim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
的sort(int[])
和uniq(int[])
功能是由提供intarray的contrib模块。
要启用它,必须安装模块。
如果您不想使用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)
...哪里有这种array_X实用程序的statandard库(?)?
尝试搜索...看到一些但没有标准:
JDBurnZ / postgresql-anyarray,主动性好,但需要一些协作来增强。
wiki.postgresql.org/Snippets是受挫的举措,但“官方wiki”需要增强一些协作。
MADlib:很好!....但它只是一头大象,而不是“纯SQL代码段库”。
array_distinct()
代码片段库功能这里是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;
注意:它适用于任何数据类型,但数组数组除外,
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:使用JSONB数组效果很好,
SELECT array_distinct( array['[3,3]'::JSONB, '[3,3]'::JSONB, '[5,6]'::JSONB] );
-- "{"[3, 3]","[5, 6]"}"
编辑:更复杂但有用,一个“ drop nulls”参数
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;
我已经组装了一组存储过程(函数),以解决PostgreSQL缺少coind的数组处理问题anyarray
。这些函数旨在跨任何数组数据类型工作,而不仅仅是像intarray这样的整数: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]
使用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;
这是“内联”方式:
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;
首先,我们从数组创建一个集合,然后仅选择不同的条目,然后将其聚合回数组。
SELECT array_agg(DISTINCT c1) FROM unnest(ARRAY[1234,5343,6353,1234,1234]) t(c1)
对于像我这样仍然需要处理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}