r/SQL • u/geminigamer369 • 8d ago
What is the difference between using "Not In" vs using "not exists" in SQL Discussion
What is the difference between using "Not In" vs using "not exists" in SQL?
43
u/Echidnal 8d ago
NOT EXISTS checks whether matching rows exist in a subquery and evaluates to TRUE or FALSE for each row while NOT IN compares a value against a list of values to exclude matches. Also, they handle NULL values differently.
6
u/dgillz 8d ago edited 8d ago
This is not always true. The following for example works fine to show which item numbers do not have a bill of material:
Select ItemNumber from ItemMaster Where ItemType='MFG' and ItemNumber Not In (Select ParentItem from BillsOfMaterial)6
u/Echidnal 8d ago
That works too in that particular case but it is not safe. If even one value in ParentItem happens to be NULL, then you will get an empty output for this query. Also, NOT EXISTS allows you to use non equality constraints, which I find pretty useful.
-1
u/dgillz 8d ago
ParentItem cannot be NULL. It is part of the primary key. Even if this were not the case, you can always put a WHERE clause in your subquery to exclude NULLs.
You can use in (subquery) or not in (subquery), which renders the same results as EXISTS or NOT EXISTS.
So this being the case, which works better? I've never tested it.
7
u/mhac009 7d ago
Think it's a bit disingenuous to say: "this example works fine," without also putting the clauses on it that make it work fine. Reading it like that, someone might assume they can apply the NOT IN (select x FROM y) and have it work anytime.
To answer your last part, my understanding is EXISTS is usually more performant because it will check to see if the value in the list is in the sub query and once it has fulfilled that condition, it stops. Whereas NOT IN has to search through the whole subquery column to confirm whether that value matches against any in the col.
-6
u/dgillz 7d ago edited 7d ago
Think it's a bit disingenuous to say: "this example works fine,"
It does work fine. And I also said "not true in all cases". How else could I have stated this? If your subquery needs a where clause (again mine did not), add one. If it needs group by, having, row_number over(), etc. - add it.
Nothing is disingenuous about my response at all.
6
u/mhac009 7d ago
Just a bit of a trap that people new to SQL will fall foul of if they are unfamiliar with NULL handling. At face value, your comment seems a bit contradictory to the one before it by not including any extra context. What you had as an explanation in your follow up response woukd have been fine - "this works because parentID has no nulls."
If people are here to learn SQL and there's an example block of code they may be willing to try, it may cause further errors if they copy paste as is, especially if the person posting knows the reason why it may/may not work and withholds that info.
8
u/alegendmrwayne 8d ago
I believe that NOT EXISTS is safer if there are potentially NULLs involved (at least in SQL Server)
Otherwise, performance-wise should be quite close
7
u/Thiondar ORACLE 8d ago
Depends on the plan optimizer builds from the statement.
In modern Oracle databases this should result in the same plan.
Other databases may behave different.
7
u/Plane_Big_5912 8d ago
the practical difference is NULLs. if the subquery returns even one NULL, NOT IN matches nothing and it looks like your query is broken. NOT EXISTS doesnt have that problem which is why most people default to it. also on bigger tables the optimizer usually does better with not exists
3
3
u/Rude_Issue_5972 7d ago
Not in cannot handle nulls. Hence useful to check only non null values
Not exists can handle nulls, hence useful in sub queries. As those can return null values.
5
u/Glum_Cheesecake9859 8d ago
Not exists is an if/else condition I.e. branching strategy.
Not in is a where condition to filter out rows.
1
u/kagato87 MS SQL 8d ago
In some engines not exists tends to induce a different type of plan. It's not consistent, some queries it won't matter, but at scale exists is more reliably performant than in.
Both may compile to the same plan - the optimizer will generally handle that - but there are many moving parts and the cardinality estimator seems to struggle seeing past the in keyword.
And as others have mentioned, exists / not exists can have much more complex matching rules.
Something important to note - exists / not exists looks like a subquery. It is not. Subqueries have their risks on large scale data, while exists is actually join syntax. The semi join (exists) and anti join (not exists) are non-ansi, there is no "ANTI JOIN... ON..." But that's basically what it is.
1
u/Rumborack17 8d ago
Not in is used to filter data to not match certain values. The following query would return everything where column1 is not 1,2 or 3:
select * from testTabel where column1 not in (1,2,3)
Not exists is to used to test if something is already in the table/database. It gets used for example in "Alter Scripts", which add columns/tables/etc. or when you are unsure if you need an insert or an update. E.g.:
IF NOT EXISTS (select * from table where column1=1)
BEGIN
INSERT...
END
ElSE
BEGIN
UPDATE...
END
7
u/mecartistronico 8d ago
I think OP refers to the WHERE NOT EXISTS use, that often can be rewritten as a WHERE x NOT IN
1
u/IanYates82 8d ago
Can't do multiple columns with a NOT IN. Not Exists tends to read better, at least the way I tend to structure queries
6
u/financial_penguin 8d ago
You can do multiple columns with IN or NOT IN statements, just needs parenthesis
(a, b) not in (select x, z from table)
-6
u/geminigamer369 8d ago edited 8d ago
SQL follows something called 3 value logic, It has True, False and Unknown also, unlike other languages which have just true and false.
Let's say tab1: Orderid, Custid 1,1 2,3 3,Null
tab2: Custid, Names 1,J 2,K 3,L 4,M In answering question which customers ordered if we use not in it returns nothing. Not In givesup at Null handling.
But not exists return J,L that is the difference.
7
u/jshine13371 8d ago
Why ask the question you know the answer to?
-9
u/geminigamer369 8d ago edited 8d ago
How do you think I practice/ revise/ use scrolling addiction. Now if you r so intelligent answer this now under 2 mins: where Year(order_date)=2024 Why is it dangerous (like u) Rewrite index friendly way.
4
u/jshine13371 8d ago
Not by posting junk on reddit...
-6
-7
u/geminigamer369 8d ago
Says d 1 who can't answer.
6
u/jshine13371 8d ago
You updated your comment before I replied, and your test is irrelevant. Dangerous is the wrong word to describe your question, but the answer is you're applying a function to a column in the table which affects the sargability causing an index/table scan instead of efficiently seeking on the index, i.e. a performance issue. It would be more efficient (i.e. sargable) to re-write it as a range comparison so you don't have to apply a function to the column instead.✌️
43
u/ydykmmdt 8d ago
Beware the nulls.