Reputation: 4094
In my case, I have two table with same structure: TableA
& TableB
, and what I was trying to do is to find if there is any records only exists in A but not B.
My script was
SELECT * FROM TableA
WHERE NOT EXISTS (
SELECT * FROM TableB
)
While there is 2 records which only exists in A but not B, this script returns nothing. Then I changed into following:
SELECT ID FROM TableA
WHERE ID NOT IN (
SELECT ID FROM TableB
)
This script works successfully and return the 2 records' ID.
My question is: Is this behavior normal? What is the mechanism behind NOT EXISTS
and NOT IN
?
I have read some other posts comparing NOT EXISTS
and NOT IN
, and most people suggest using NOT EXISTS
in 99.9% scenarios, is this case fall into that 0.1% which NOT EXISTS
is not applicable? (I believed it's due to my wrongly usage though, please correct me if that's the case)
Upvotes: 0
Views: 57
Reputation: 10411
You need to be careful with the NOT IN
expression.
The A NOT IN(B,C,D)
expression basically means (A<>B AND A<>C AND A<>D)
. If any of the values are NULL the whole expression will become NULL.
So, applicable to your example the correct NOT IN expression should be (unless the ID is not nullable column):
SELECT ID FROM TableA
WHERE ID NOT IN (
SELECT ID FROM TableB WHERE ID IS NOT NULL
)
Upvotes: 1
Reputation: 1270573
If you want to look at all the values in the rows, then use EXCEPT
:
SELECT *
FROM TableA
EXCEPT
SELECT *
FROM TableB;
If you want to use NOT EXISTS
correctly, then you need a correlation clause:
SELECT a.*
FROM TableA a
WHERE NOT EXISTS (SELECT 1 FROM TableB b WHERE b.id = a.id);
I strongly recommend using NOT EXISTS
over NOT IN
with a subquery. NOT IN
will return no rows at all if b.id
is ever NULL
. That is usually not what is intended. NOT EXISTS
matches the expected semantics.
Upvotes: 3