tags:

views:

226

answers:

7

I have two tables that are joined together.

A has many B

Normally you would do:

select * from a,b where b.a_id = a.id

To get all of the records from a that has a record in b.

How do I get just the records in a that does not have anything in b?

+6  A: 
select * from a where id not in (select a_id from b)

Or like some other people on this thread says:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null
AlbertEin
You beat me to it by five seconds! <grin>
BlackWasp
wow.. identical answers!
Marcel Tjandraatmadja
somethimes you win, sometimes you lose =P
AlbertEin
well, there isn't too many ways to do that
AlbertEin
Ah well. Never mind eh? :-D
BlackWasp
Thanks guys! Amazing that StackOverflow is faster than Google now.
Sixty4Bit
Too many spare time to few places to spend it =P
AlbertEin
+2  A: 

select * from a where id not in (select a_id from b)

BlackWasp
This will be extremely expensive as the engine has to generate the the subquery in its entirety before it can begin to eliminate the tuples from a. Not a good idea in general.
dland
+5  A: 
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
Joseph Anderson
I think this left outer join will perform much better than the 'in' clause, unless the query optimizer treats them the same...
Codewerks
It pretty much does. Check it out.
David B
Yeah, interestingly, the query plan has an extra strep (Filter) for the left join and the 'where in' is resolved to a 'right anti semi join'...whatever that is...
Codewerks
+4  A: 

Another approach:

select * from a where not exists (select * from b where b.a_id = a.id)

The "exists" approach is useful if there is some other "where" clause you need to attach to the inner query.

Matt Hamilton
A: 

You will probably get a lot better performance (than using 'not in') if you use an outer join:

select * from a left outer join b on a.id = b.a_id where b.a_id is null;
nathan
A: 

Another way of writing it

select a.* from a left outer join b on a.id = b.id where b.id is null

Ouch, beaten by Nathan :)

shahkalpesh
A: 

This will protect you from nulls in the IN clause, which can cause unexpected behavior.

select * from a where id not in (select [a id] from b where [a id] is not null)

David B
You are better off using a left outer join rather than using an IN predicate in the first place.
dland
Any reason for this opinion?
David B