Postgres - Функция возврата пересечения двух массивов?
В postgresql вы можете использовать && оператор возвращает t (true), если два массива имеют общие элементы, т.е. перекрываются. Есть ли функция/оператор, который вернет то, что эти общие члены?
то есть. что-то вроде этого
select arrray_intersection(ARRAY[1, 4, 2], ARRAY[2, 3]);
ARRAY[2]
Ответы
Ответ 1
Начиная с 8.4, в Postgres есть полезные встроенные функции, которые делают функцию из первого ответа проще и, возможно, быстрее (то, что EXPLAIN мне говорит, в любом случае: "(cost = 0.00..0.07 rows = 1 width = 64)" для этого запроса против "(cost = 0.00..60.02 rows = 1 width = 64)" для оригинала).
Упрощенный код:
SELECT ARRAY
(
SELECT UNNEST(a1)
INTERSECT
SELECT UNNEST(a2)
)
FROM (
SELECT array['two', 'four', 'six'] AS a1
, array['four', 'six', 'eight'] AS a2
) q;
и да, вы можете превратить его в функцию:
CREATE FUNCTION array_intersect(anyarray, anyarray)
RETURNS anyarray
language sql
as $FUNCTION$
SELECT ARRAY(
SELECT UNNEST($1)
INTERSECT
SELECT UNNEST($2)
);
$FUNCTION$;
который вы можете назвать
SELECT array_intersect(array['two', 'four', 'six']
, array['four', 'six', 'eight']);
Но вы также можете назвать его встроенным:
SELECT array(select unnest(array['two', 'four', 'six']) intersect
select unnest(array['four', 'six', 'eight']));
Ответ 2
Попробуйте &
вместо &&
Подробнее см. Документы PostgreSQL.
Ответ 3
SELECT ARRAY
(
SELECT a1[s]
FROM generate_series(array_lower(a1, 1), array_upper(a1, 1)) s
INTERSECT
SELECT a2[s]
FROM generate_series(array_lower(a2, 1), array_upper(a2, 1)) s
)
FROM (
SELECT array['two', 'four', 'six'] AS a1, array['four', 'six', 'eight'] AS a2
) q
Работает и с нецелыми массивами.
Ответ 4
Вы можете использовать эту функцию:
CREATE OR REPLACE FUNCTION intersection(anyarray, anyarray) RETURNS anyarray as $$
SELECT ARRAY(
SELECT $1[i]
FROM generate_series( array_lower($1, 1), array_upper($1, 1) ) i
WHERE ARRAY[$1[i]] && $2
);
$$ language sql;
Он должен работать с любым типом массива, и вы можете использовать его следующим образом:
SELECT intersection('{4,2,6}'::INT4[], '{2,3,4}'::INT4[]);
Ответ 5
один другой способ.
SELECT ARRAY( SELECT * FROM UNNEST( $1 ) WHERE UNNEST = ANY( $2 ) );
Ответ 6
Если вы не возражаете против установки расширения, расширение intarray предоставляет оператор &
для этого, поскольку @dwc указал.
SELECT ARRAY[1, 4, 2] & ARRAY[2, 3];
Возвращает {2}
.