유형의 배열이 bigint
있습니다. 해당 배열에서 중복 값을 제거하려면 어떻게해야합니까?
전의: array[1234, 5343, 6353, 1234, 1234]
나는 얻어야한다 array[1234, 5343, 6353, ...]
SELECT uniq(sort('{1,2,3,2,1}'::int[]))
postgres 매뉴얼 의 예제 를 테스트 했지만 작동하지 않습니다.
답변:
나는 똑같이 직면했다. 하지만 제 경우에는 배열이 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 라이브러리 (?)는 어디에 있습니까 ?
검색해보십시오 ... 표준은 아니지만 일부보기 :
postgres.cz/wiki/Array_based_functions : 좋은 참조입니다!
JDBurnZ / postgresql-anyarray , 좋은 이니셔티브이지만 개선하려면 일부 협력이 필요합니다.
wiki.postgresql.org/Snippets , 실망스러운 이니셔티브이지만 "공식 위키"는 향상시키기 위해 약간의 협력이 필요합니다.
MADlib : 좋아요! .... 그러나 이것은 "순수 SQL 스 니펫 lib"가 아니라 코끼리입니다.
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;
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]
사용 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)
단일 쿼리에서 다음을 수행했습니다.
SELECT (select array_agg(distinct val) from ( select unnest(:array_column) as val ) as u ) FROM :your_table;
여전히 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}