2009-04-16 5 views
18

Dans postgresql, vous pouvez utiliser l'opérateur & & pour renvoyer t (true) si deux tableaux ont des membres communs, c'est-à-dire qu'ils se chevauchent. Y a-t-il une fonction/opérateur qui retournera ce que sont ces membres communs?Postgres - Fonction pour retourner l'intersection de 2 ARRAY?

dire quelque chose comme ça

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

Répondre

14

Essayez & au lieu de &&

Voir PostgreSQL Docs pour plus.

+3

Testé, ne fonctionne pas en stock, vous avez besoin d'une extension installée pour le faire fonctionner. mais +1 de toute façon. –

+1

http://www.postgresql.org/docs/current/static/contrib.html # besoin de lire les données ici –

+0

Bonne capture, 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 

Fonctionne également sur les tableaux non entiers.

3

Vous pouvez utiliser cette fonction:

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; 

Il devrait fonctionner avec tout type de tableau, et vous pouvez l'utiliser comme ceci:

SELECT intersection('{4,2,6}'::INT4[], '{2,3,4}'::INT4[]); 
39

Since 8.4, there are useful builtins in Postgres qui rendent the function from the first answer plus facile et peut-être plus rapide (c'est ce que EXPLAIN me dit, de toute façon: "(coût = 0.00..0.07 lignes = 1 largeur = 64)" pour cette requête vs "(coût = 0.00..60.02 lignes = 1 largeur = 64)" pour l'original) .

Le code simplifié est:

SELECT ARRAY 
    (
     SELECT UNNEST(a1) 
     INTERSECT 
     SELECT UNNEST(a2) 
    ) 
FROM (
     SELECT array['two', 'four', 'six'] AS a1 
       , array['four', 'six', 'eight'] AS a2 
    ) q; 

et oui, vous pouvez le transformer en fonction:

CREATE FUNCTION array_intersect(anyarray, anyarray) 
    RETURNS anyarray 
    language sql 
as $FUNCTION$ 
    SELECT ARRAY(
     SELECT UNNEST($1) 
     INTERSECT 
     SELECT UNNEST($2) 
    ); 
$FUNCTION$; 

que vous pouvez appeler comme

SELECT array_intersect(array['two', 'four', 'six'] 
        , array['four', 'six', 'eight']); 

Mais vous pouvez juste ainsi appeler en ligne aussi:

SELECT array(select unnest(array['two', 'four', 'six']) intersect 
       select unnest(array['four', 'six', 'eight'])); 
2

une autre méthode ..

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

Si vous ne me dérange pas d'installer une extension, le intarray extension fournit à l'opérateur & de le faire comme @dwc a souligné .:

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

Retours {2}.

+0

Quelle version postgresql utilisez-vous? Avec 9.6 j'obtiens l'erreur ci-dessous et je ne peux pas non plus le trouver dans les docs. Ou est-ce que je fais quelque chose de mal ici? '' 'ERREUR: l'opérateur n'existe pas: entier [] & entier [] LIGNE 1: SELECT ARRAY [1,4,2] & ARRAY [2,3] ^ ASTUCE: Aucun opérateur ne correspond au prénom et type (s) d'argument. Vous devrez peut-être ajouter un type explicite castings.''' –

+2

Ah, attendez, comme https: //www.postgresql.org/docs/current/static/intarray.html, c'est une extension de postgresql. Cela vaut la peine de le mentionner. –

Questions connexes