Объединение двух массивов в PostgreSQL без unnesting

у меня есть два массива в PostgreSQL, которые мне нужно объединить. Например:

{1,2,3} Союз {1,4,5} вернутся {1,2,3,4,5}

использование оператора concatenate ( | | ) не удаляет повторяющиеся записи, т. е. возвращает {1,2,3,1,4,5}

я нашел одно решение в интернете, однако мне не нравится, как нужно отменить оба массива: select ARRAY(select unnest(ARRAY[1,2,3]) as a UNION select unnest(ARRAY[2,3,4,5]) as a)

есть ли оператор или встроенная функция, которая будет чисто объединять два массива?

3 ответов


Если ваша проблема в unnest дважды, это будет unnest только один раз

select array_agg(a order by a)
from (
    select distinct unnest(array[1,2,3] || array[2,3,4,5]) as a
) s;

есть расширение intarray с (в пакете contrib), который содержит некоторые полезные функции и операторы:

postgres=# create extension intarray ;
CREATE EXTENSION

с одиночным оператором трубы:

postgres=# select array[1,2,3] | array[3,4,5];
  ?column?   
─────────────
 {1,2,3,4,5}
(1 row)

или :

postgres=# select uniq(ARRAY[1,2,3] || ARRAY[3,4,5]);
    uniq     
─────────────
 {1,2,3,4,5}
(1 row)

ANSI/SQL знает multiset, но он еще не поддерживается PostgreSQL.


можно сделать так...

select uniq(sort(array_remove(array_cat(ARRAY[1,2,3], ARRAY[1,4,5]), NULL)))

выдает:

{1,2,3,4,5}

array_remove необходим, потому что вы не можете сортировать массивы с нулями. Сортировка необходима, потому что uniq де-дублирует, только если найдены смежные элементы.

преимущество этого подхода над @Clodoaldo Neto заключается в том, что он работает целиком в select и не является unnest в предложении FROM. Это делает его простым для работы с несколькими столбцами массивов одновременно и в одном сканирование таблицы. (Хотя см. версию Ryan Guill как функцию в комментарии).

кроме того, этот шаблон работает для всех типов массивов (элементы who сортируются).

недостатком является то, что, возможно, его немного медленнее для более длинных массивов (из-за сортировки и 3 промежуточных распределений массива).

Я думаю, что и это, и ответ accept не удастся, если вы хотите сохранить NULL в результате.