postgres에서 중복 배열 값 제거


87

유형의 배열이 bigint있습니다. 해당 배열에서 중복 값을 제거하려면 어떻게해야합니까?

전의: array[1234, 5343, 6353, 1234, 1234]

나는 얻어야한다 array[1234, 5343, 6353, ...]

SELECT uniq(sort('{1,2,3,2,1}'::int[]))postgres 매뉴얼 의 예제 를 테스트 했지만 작동하지 않습니다.

답변:


95

나는 똑같이 직면했다. 하지만 제 경우에는 배열이 array_agg함수 를 통해 생성됩니다 . 다행히 다음 과 같이 DISTINCT 값 을 집계 할 수 있습니다 .

  array_agg(DISTINCT value)

이것은 나를 위해 작동합니다.


5
DISTINCT는 창 함수에 대해 지원되지 않습니다.
Thinkable

TKS 사람trim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
파 비우 Zangirolami

4
select array_agg (DISTINCT Array [1,2,2,3])는 "{{1,2,2,3}}"를 제공합니다
user48956

당신이 값으로 배열을 입력 할 때, 쿼리에 의해 그룹화 값으로 단일 열 설정해야합니다, 논리적 @ user48956,
다니엘 TULP

83

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)

1
문제의 해결책 ( "중복 된 배열 값 제거")은 정렬 할 필요가 없습니다 . 일반적으로 유용한 기능이지만이 컨텍스트 / 요구 사항에서는 불필요합니다 (CPU 비용).
Peter Krauss

27

... 이런 종류의 array_X 유틸리티를 위한 statandard 라이브러리 (?)는 어디에 있습니까 ?

검색해보십시오 ... 표준은 아니지만 일부보기 :


가장 간단하고 빠른 array_distinct()snippet-lib 함수

여기에 array_unique()or에 대한 가장 간단하고 빠른 구현이 있습니다 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}"

"부작용"은 요소 집합의 모든 배열을 분해하는 것입니다.

추신 : 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;

FROM unnest ($ 1) t (x)에서 t (x)가 무엇을하고 있는지 설명해 주시겠습니까? ... 또한 삽입 된 항목의 순서를 어떻게 유지할 수
있습니까?

@ abhirathore2006이 답변은 Wiki이며 제안한 설명을 작성할 수 있습니다. "순서 유지"정보, 아니요, 파괴적인 솔루션입니다. 원래 어레이 순서를 유지하려면이 페이지의 PLpgSQL 솔루션을 참조하십시오. 그것은 또한 두 가지 요구 사항, 정렬구별입니다 ( 여기 에서 주요 답변의 성공 과 거기에 내 의견 참조).
Peter Krauss

걱정 아니, 난 이미 PLSQL 솔루션을 다른 곳, 예로부터 해결책을 발견
abhirathore2006

13

PostgreSQL의 배열 처리 부족에 맞서기 위해 일련의 저장 프로 시저 (함수)를 모았습니다 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]


13

사용 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;

1
베스트 답변! 참조 : dba.stackexchange.com/questions/211501/…
fjsj

9

"인라인"방법은 다음과 같습니다.

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;

먼저 배열에서 집합을 만든 다음 고유 항목 만 선택한 다음 다시 배열로 집계합니다.


9
또는 "more inline";-) SELECT array_agg(DISTINCT c1) FROM unnest(ARRAY[1234,5343,6353,1234,1234]) t(c1)
Peter Krauss

4

단일 쿼리에서 다음을 수행했습니다.

SELECT (select array_agg(distinct val) from ( select unnest(:array_column) as val ) as u ) FROM :your_table;


3

여전히 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}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.