I ran
Select Term from TableA where Term not in (Select Name from TableB)
successfully. Yet when I tried another table
Select Term from TableA where Term not in (Select Name from TableC)
It returns a NULL set. I manuallyt confirmed there are literaly 1000s of records in TableA not in TableB and that the fields are correct.
Is there some other consideration I am not taking into account/understanding about what seems to be a simply query?
Update: Interestingly enough this alternative query worked:
Select Term from TableA where not exist (Select Name from TableB where TableA.Term=TableC.Name)
So while I solved the problem at hand I am still curious why the first query worked for both tables but only the second worked on TableC
CodePudding user response:
For a simple example, consider the following query:
SELECT *
FROM Table
WHERE ID NOT IN (1, 2, NULL);
This is semantically equivalent to:
SELECT *
FROM Table
WHERE ID <> 1 AND ID <> 2 AND ID <> NULL;
The issue is with the last predicate (ID <> NULL
). Nothing can be equal to null (not even null) and nothing can be not equal to null. The predicate returns neither true nor false, it returns NULL.
e.g.
ID | ID <> 1 | ID <> 2 | ID <> NULL |
---|---|---|---|
1 | FALSE | TRUE | NULL |
2 | TRUE | FALSE | NULL |
3 | TRUE | TRUE | NULL |
Since you need 3 "TRUE"s to satisfy the AND
condition, no rows are returned, since none resolve to true for all 3 predicates.
You can get your NOT IN
to work by excluding nulls, e.g.
SELECT Term
FROM TableA
WHERE Term NOT IN (SELECT Name FROM TableC WHERE Name IS NOT NULL);
But for this reason, and the potential for name clashes I always use NOT EXISTS
.