Hi Tom,
you need 3 count one for overall for each id, second one for matched per id and third one for no of item in the list as below
SQL> select * from test;
ID X
---------- ----------
1 1
1 2
1 3
1 4
2 1
2 2
2 3
3 1
3 2
4 1
4 6
ID X
---------- ----------
3
12 rows selected.
SQL> exec :txt:='1'
PL/SQL procedure successfully completed.
SQL> ed
Wrote file afiedt.buf
1 with data as
2 (
3 select level, length(txt)-length(replace(txt,',',''))-1 as itm_cnt,
4 trim(substr (txt,
5 instr (txt, ',', 1, level ) + 1,
6 instr (txt, ',', 1, level+1)
7 - instr (txt, ',', 1, level) -1 )) as tkn
8 from (select ','||:txt||',' txt
9 from dual)
10 connect by level <
11 length(txt)-length(replace(txt,',',''))
12 )
13 select distinct id
14 from
15 (
16 select id, x, d.tkn, d.itm_cnt, tot_cnt, count(*)over(partition by t.id) as match_cnt
17 from
18 (select id, x, count(*)over(partition by id) as tot_cnt
19 from test ) t Join data d
20 on t.x=d.tkn
21* )where itm_cnt=tot_cnt and tot_cnt=match_cnt
22 /
no rows selected
SQL> exec :txt:='1,2'
PL/SQL procedure successfully completed.
SQL> /
no rows selected
SQL> exec :txt:='1,2,3'
PL/SQL procedure successfully completed.
SQL> /
ID
----------
2
SQL> exec :txt:='1,2,3,4'
PL/SQL procedure successfully completed.
SQL> /
ID
----------
1
SQL> exec :txt:='1,2,3,4,5'
PL/SQL procedure successfully completed.
SQL> /
no rows selected
SQL> delete from test where x is null
2 ;
1 row deleted.
SQL> select * from test;
ID X
---------- ----------
1 1
1 2
1 3
1 4
2 1
2 2
2 3
3 1
3 2
4 1
4 6
11 rows selected.
SQL> exec :txt:='1,2'
PL/SQL procedure successfully completed.
SQL> ed
Wrote file afiedt.buf
1 with data as
2 (
3 select level, length(txt)-length(replace(txt,',',''))-1 as itm_cnt,
4 trim(substr (txt,
5 instr (txt, ',', 1, level ) + 1,
6 instr (txt, ',', 1, level+1)
7 - instr (txt, ',', 1, level) -1 )) as tkn
8 from (select ','||:txt||',' txt
9 from dual)
10 connect by level <
11 length(txt)-length(replace(txt,',',''))
12 )
13 select distinct id
14 from
15 (
16 select id, x, d.tkn, d.itm_cnt, tot_cnt, count(*)over(partition by t.id) as match_cnt
17 from
18 (select id, x, count(*)over(partition by id) as tot_cnt
19 from test ) t Join data d
20 on t.x=d.tkn
21* )where itm_cnt=tot_cnt and tot_cnt=match_cnt
22 /
ID
----------
3
SQL>