Reputation: 89
I am trying to find records which exists in table A but not in table B. If there is only one column to check, then I can use
select col_A,col_B,......from A where col_A not in (select Col_A from B).
But I have four columns which need to checked.
I did something like this, which works but is not the perfect way
select col_A,col_B,col_C,col_D from A where col_A||col_B||col_C||col_D not in (select col_A||col_B||col_C||col_D from B)
and also it takes lot of time to return results in case of large amount of data.
Please suggest the proper way of doing this.
Thanks.....
Upvotes: 3
Views: 5916
Reputation: 496
From Oracle documentation
http://docs.oracle.com/cd/E11882_01/server.112/e26088/queries004.htm#SQLRF52341
"MINUS Example The following statement combines results with the MINUS operator, which returns only unique rows returned by the first query but not by the second:"
SELECT product_id FROM inventories
MINUS
SELECT product_id FROM order_items;
You requirements are a little bit more complicated. I assume, that the combination of cols_a, cols_b, cols_c, cols_d is unique for a record in table A. In that case, the following code should solve your problem:
create table A (
cols_date DATE,
cols_a NUMBER,
cols_b NUMBER,
cols_c NUMBER,
cols_d NUMBER
);
create table B (
cols_a NUMBER,
cols_b NUMBER,
cols_c NUMBER,
cols_d NUMBER
);
insert into A (cols_date, cols_a, cols_b, cols_c, cols_d) values (sysdate, 1, 1, 1, 1);
insert into A (cols_date, cols_a, cols_b, cols_c, cols_d) values (sysdate, 2, 2, 2, 2);
insert into B (cols_a, cols_b, cols_c, cols_d) values (2, 2, 2, 2);
insert into B (cols_a, cols_b, cols_c, cols_d) values (3, 3, 3, 3);
commit;
select a.cols_date, a.cols_a, a.cols_b, a.cols_c, a.cols_d from (
select cols_a, cols_b, cols_c, cols_d
from A
minus
select cols_a, cols_b, cols_c, cols_d
from b
) ma, a
where 1=1
and ma.cols_a = a.cols_a
and ma.cols_b = a.cols_b
and ma.cols_c = a.cols_c
and ma.cols_d = a.cols_d;
Result is
COLS_DATE COLS_A COLS_B COLS_C COLS_D
--------------------- ---------- ---------- ---------- ----------
01.07.2013 13:20:02 1 1 1 1
NOT EXISTS will also solve the problem. This statement has a better execution plan then the MINUS version.
Thanks to David Aldridge for this solution.
select
cols_date,
cols_a, cols_b, cols_c, cols_d
from
a
where
not exists (
select 1
from b
where 1=1
and b.cols_a = a.cols_a
and b.cols_b = a.cols_b
and b.cols_c = a.cols_c
and b.cols_d = a.cols_d
);
Upvotes: 6
Reputation: 52336
There's an implicit distinct on MINUS that you'd probably want to avoid.
A NOT EXISTS construct would probably be run as a hash anti-join, which would be very efficient.
select
col1,
col2,
col3,
... etc
from
table_a a
where
not exists (
select null
from table_b b
where a.col1 = b.col1 and
a.col2 = b.col2 and
a.col3 = b.col3 and
a.col4 = b.col4)
Upvotes: 3
Reputation: 19247
WITH mine AS (
SELECT cols_a, cols_b, cols_c, cols_d FROM a
MINUS
SELECT cols_a, cols_b, cols_c, cols_d FROM b
)
SELECT a.cols_date, a.cols_a, a.cols_b, a.cols_c, a.cols_d
FROM a NATURAL JOIN mine
Upvotes: 1