У меня есть массив типа bigint
, как я могу удалить повторяющиеся значения в этом массиве?
Пример: array[1234, 5343, 6353, 1234, 1234]
Я должен получить array[1234, 5343, 6353, ...]
Я протестировал пример SELECT uniq(sort('{1,2,3,2,1}'::int[]))
в руководстве по postgres, но он не работает.
postgresql
ГВК
источник
источник
trim(string_agg(distinct to_char(z.dat_codigo,'0000000000'),'')) as dat_codigo,
sort(int[])
Иuniq(int[])
функции обеспечиваются INTArray модулем вно.Чтобы включить его использование, необходимо установить модуль .
Если вы не хотите использовать модуль 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 ??
Попробуйте поискать ... Посмотрите некоторые, но не стандартные:
postgres.cz/wiki/Array_based_functions : хорошая ссылка!
JDBurnZ / postgresql-anyarray , хорошая инициатива, но требует некоторого сотрудничества для улучшения.
wiki.postgresql.org/Snippets , неудовлетворенная инициатива, но «официальная вики», требует некоторого сотрудничества для улучшения.
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;
ПРИМЕЧАНИЕ: он работает должным образом с любым типом данных, кроме массива массивов,
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]"}"
Изменить: более сложный, но полезный параметр "отбрасывать нули"
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]);
дам
источник