-
Website
http://awads.net/wp/ -
Original page
http://awads.net/wp/2005/10/11/sql-problem/ -
Subscribe
All Comments -
Community
-
Top Commenters
-
jgarry
3 comments · 1 points
-
Andy C
22 comments · 47 points
-
dahowlett
1 comment · 2 points
-
Don Seiler
9 comments · 1 points
-
davidhaimes
4 comments · 3 points
-
-
Popular Threads
create or replace type tablist as table of varchar2(255);
create or replace function my_comma_to_table(csv varchar2)
return tablist is
l_string long default csv || ',';
l_data tablist := tablist();
n number;
begin
loop
exit when l_string is null;
n := instr( l_string, ',' );
l_data.extend;
l_data(l_data.count) :=
ltrim( rtrim( substr( l_string, 1, n-1 ) ) );
l_string := substr( l_string, n+1 );
end loop;
return l_data;
end my_comma_to_table;
select * from t
where 0=(select cnt_a-cnt_b
from (select count(*) cnt_a
from (select to_number(column_value)
from table(cast (my_comma_to_table('1,2,2') as tablist))
union select id from t)) a,
(select count(*) cnt_b from t) b
)
/
The above would handle even when the list contains alphanumeric values. In that case just remove the to\_number function in the select query.
Regards
Partha
scott: select * from t
2 where 0=(select cnt_a-cnt_b
3 from (select count(*) cnt_a
4 from (select column_value
5 from table(cast (my_comma_to_table('1,a,2') as tablist))
6 union select id from t)) a,
7 (select count(*) cnt_b from t) b
8 )
9 /
from (select column_value
*
ERROR at line 4:
ORA-01790: expression must have same datatype as
corresponding expression
scott: select * from t
2 where 0=(select cnt_a-cnt_b
3 from (select count(*) cnt_a
4 from (select column_value
5 from table(cast (my_comma_to_table('1,a,2') as tablist))
6 union select to_char(id) from t)) a,
7 (select count(*) cnt_b from t) b
8 )
9 /
no rows selected
create table id_tab (id number);
insert into id_tab select rn
from (select rownum rn from dba_objects) where mod(rn, 20) != 0;
insert into id_tab select rn
from (select rownum rn from dba_objects) where mod(rn, 10) != 0;
insert into id_tab select rn
from (select rownum rn from dba_objects) where mod(rn, 5) != 0;
commit;
create table id_domain (id number);
insert into id_domain select rownum from dba_objects where rownum
select id
from (
select t.id, count(distinct t.id) over () cnt1, cnt2
from (
select id, count(id) over () cnt2
from id_domain
where id in (1,2,17,17)
) p, id_tab t
where t.id = p.id
)
where cnt1 = cnt2;
select id
from (
select id
from id_tab
where id in (1,2,17,17)
)
where not exists (
select null
from id_domain
where id in (1,2,17,17)
and id not in (
select id
from id_tab
)
);
jeffkemponoracle.blogspot.com/2005/10/sql-problem.html
Depends on whether they want to pass the list as a single variable (which will need parsing into its components using PL/SQL as per Partha's solution).
create table t(id number);
insert into t values(1);
insert into t values(2);
select * from
(select t.id, x.column_value x,
count(distinct x.column_value) over () count_x,
count(distinct t.id) over () count_t
from t, table(sys.dbms_debug_vc2coll(1,2,3)) x
where t.id(+) = to_number(x.column_value))
where count_x = count_t
/
select * from
(select t.id, x.column_value x,
count(distinct x.column_value) over () count_x,
count(distinct t.id) over () count_t
from t, table(sys.dbms_debug_vc2coll(1,2)) x
where t.id(+) = to_number(x.column_value))
where count_x = count_t
/
select * from
(select t.id, x.column_value x,
count(distinct x.column_value) over () count_x,
count(distinct t.id) over () count_t
from t, table(sys.dbms_debug_vc2coll(1)) x
where t.id(+) = to_number(x.column_value))
where count_x = count_t
/
Jeff's solution was what I wanted to acheive, but really could not get it working. I got around to it using Set Union, but not a very neat solution. Please note the trick for removing duplicate values was using a Set operation. Jeff's solution could be further improved by removing the where id in clause completely. The Set minus operation does the job neatly.
So using the improvement on Jeff's solution and using any method to manipulate the input list, the solution could be as below :
select * from t
where not exists (
select to_number(column_name)
from Input_Table
minus
select id from t)
The *`Input_Table`* can be computed from input list of values either using PL/SQL method (Partha), `sys.dbms_debug_vc2coll` (Gary) or temporary table method (Jeff). This would be driven by the assumptions you make of the input data set.
The *`column_name`* would be `column_name` in case of PL/SQL method, `column_value` in case of `dbms_debug_vc2coll` method or the column name of the temporary table in case of temporary table method.
SQL> select * from t;
ID
----------
1
2
3
SQL> select * from u;
ID
----------
1
2
3
SQL> insert into t values (4);
1 row created.
SQL> select * from t
where not exists (select id from u minus select id from t);
ID
----------
1
2
4
3
SQL> select * from t where id in (select id from u)
and not exists (select id from u minus select id from t);
ID
----------
1
2
3
-- in the first query, 4 is incorrectly returned, yes?
Another case of needing to get the exact user requirements...
select * from table(sys.KU$_OBJNUMSET(&1)) b where not exists (
select * from t c where c.id=b.column_value))