消除postgres中的重复数组值

时间:2010-10-22 06:54:35

标签: postgresql

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

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

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

我在postgres手册中测试了示例SELECT uniq(sort('{1,2,3,2,1}'::int[])),但它无效。

9 个答案:

答案 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 (?) ??

尝试搜索...查看一些但没有标准:

最简单,更快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)