1
votes

Comparaison de 2 listes dans Oracle

J'ai 2 listes que je dois comparer. Je dois trouver si au moins un élément de la liste A se trouve dans la liste B. Je sais que IN ne fonctionne pas avec 2 listes. Quelles sont mes autres options?

En gros, quelque chose comme ceci:

SELECT 
CASE WHEN ('A','B','C') IN ('A','Z','H') THEN 1 ELSE 0 END "FOUND"
FROM DUAL

J'apprécierais toute aide!


2 commentaires

Celui de gauche n'est pas une liste, mais un "tuple".


Il n'y a pas de «listes» dans Oracle. Où se trouvent les chaînes «A», «B», «C» - dans une collection PL / SQL (varray, table imbriquée, etc.)? Dans une table relationnelle standard? Ou dans un autre objet de base de données qui existe réellement dans Oracle? Comme je l'ai dit, "liste" n'est pas un type d'objet dans Oracle.


5 Réponses :


1
votes

Vous devez répéter les conditions:

SELECT (CASE WHEN 'A' IN ('A', 'Z', 'H') OR
                  'B' IN ('A', 'Z', 'H') OR
                  'C' IN ('A', 'Z', 'H')
             THEN 1 ELSE 0
        END) as "FOUND"
FROM DUAL


0 commentaires

2
votes

Dans Oracle, vous pouvez faire:

select
  count(*) as total_matches
from table(sys.ODCIVarchar2List('A', 'B', 'C')) x, 
     table(sys.ODCIVarchar2List('A', 'Z', 'H')) y
where x.column_value = y.column_value;


0 commentaires

2
votes

Vous cherchez probablement quelque chose comme ça. La clause WITH est là juste pour simuler vos "listes" (quoi que vous entendiez par là); ils ne font pas vraiment partie de la solution. La requête dont vous avez besoin ne contient que les trois dernières lignes (plus le point-virgule à la fin).

with
  first_list (str) as (
    select 'A' from dual union all 
    select 'B' from dual union all 
    select 'C' from dual
  ),
  second_list(str) as (
    select 'A' from dual union all 
    select 'Z' from dual union all 
    select 'H' from dual
  )
select case when exists (select * from first_list f join second_list s 
                                       on f.str = s.str) then 1 else 0 end as found
from   dual
;

     FOUND
----------
         1


0 commentaires

1
votes

Si vous travaillez avec une collection de chaînes, vous pouvez essayer les opérateurs multiset.

-- union of elemtns
select * from table(coll_of_varchar2('A','B','C') multiset union distinct coll_of_varchar2('A','Z','H'));
select * from table(coll_of_varchar2('A','B','C') multiset union all coll_of_varchar2('A','Z','H'));

-- eelemnt from col1 not in col2
select * from table(coll_of_varchar2('A','A','B','C') multiset except all coll_of_varchar2('A','Z','H'));
select * from table(coll_of_varchar2('A','A','B','C') multiset except distinct coll_of_varchar2('A','Z','H'));

-- check if col1 is subset col2
select * from dual where coll_of_varchar2('B','A') submultiset coll_of_varchar2('A','Z','H','B');

et:

-- check if exits
select * from  dual where cardinality (coll_of_varchar2('A','B','C') multiset intersect coll_of_varchar2('A','Z','H')) > 0;
-- list of maching elments
select * from table(coll_of_varchar2('A','B','C') multiset intersect coll_of_varchar2('A','Z','H'));

En plus:

create type coll_of_varchar2 is table of varchar2(4000);


0 commentaires

0
votes

J'essaie de faire quelque chose de très similaire mais la première liste est un autre champ de la même requête créée avec listagg et contenant des nombres entiers comme:

SELECT 
CASE WHEN my_first_list IN ('1,2,3') THEN 1 ELSE 0 END "FOUND"
FROM DUAL

et retourne-le avec tous les autres champs que je retourne déjà

LISTAGG(my_first_list,', ') WITHIN GROUP(
        ORDER BY
            my_id
    ) my_first_list


0 commentaires