2009-04-16 2 views
18

В postgresql вы можете использовать оператор для возврата t (true), если два массива имеют общие элементы, то есть они перекрываются. Есть ли функция/оператор, который вернет то, что эти общие члены?Postgres - Функция, чтобы вернуть пересечение 2 ARRAY?

т.е. что-то вроде этого

select arrray_intersection(ARRAY[1, 4, 2], ARRAY[2, 3]); 
ARRAY[2] 

ответ

14

Попробуйте & вместо &&

PostgreSQL Docs См больше.

+3

Протестировано, не работает на складе, вам необходимо установить расширение, чтобы оно работало. но +1 в любом случае. –

+1

http://www.postgresql.org/docs/current/static/contrib.html # необходимо прочитать данные здесь –

+0

Good catch, Kent – dwc

4
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 

Работает также с нецелыми массивами.

3

Вы можете использовать эту функцию:

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[]); 
39

Since 8.4, there are useful builtins in Postgres которые делают the function from the first answer проще и, возможно, быстрее (вот что говорит мне 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

один другой способ ..

SELECT ARRAY(SELECT * FROM UNNEST($1) WHERE UNNEST = ANY($2)); 
3

Если вы не против установки расширения, то intarray extension обеспечивает & оператору, чтобы сделать это, как @dwc указал .:

SELECT ARRAY[1, 4, 2] & ARRAY[2, 3]; 

Возвраты {2}.

+0

Какую версию postgresql вы используете? С 9.6 я получил ошибку ниже, и я также не могу найти ее в документах. Или я делаю что-то не так? '' 'ERROR: оператор не существует: integer [] & integer [] LINE 1: SELECT ARRAY [1,4,2] & ARRAY [2,3] ^ СОВЕТ: Оператор не соответствует указанному имени и тип аргументов. Возможно, вам придется добавить явные типы cast. '' ' –

+2

Ах, подождите, согласно https://www.postgresql.org/docs/current/static/intarray.html, это расширение для postgresql. Стоит отметить это. –

Смежные вопросы