What is the difference between EXISTS and IN?
Quick Answer
EXISTS checks whether a subquery returns any row and stops at the first match — a semi-join. IN compares a value against a list or subquery result. They usually optimise to the same plan, but NOT IN has a dangerous quirk: if the subquery returns any NULL, NOT IN returns no rows at all.
EXISTS just asks “does this subquery return anything?” and short-circuits on the first row. IN checks a value against a set. Performance-wise they're usually the same plan for correlated checks. The real reason I reach for NOT EXISTS over NOT IN is the null trap: if the NOT IN subquery returns even one NULL, the whole condition evaluates to unknown and you get no rows back — a silent, surprising bug. NOT EXISTS doesn't have that problem.
NOT IN+ NULL:WHERE x NOT IN (SELECT y FROM t)— if anyyisNULL, the whole predicate becomesUNKNOWNand you get zero rows.NOT EXISTShandles nulls correctly.- Performance: for correlated existence checks, modern SQL Server optimises
IN,EXISTSand= ANYsimilarly.EXISTScan be clearer intent and is null-safe. - JOIN vs EXISTS: a
JOINthat thenDISTINCTs to remove duplicates from the right side is often better written asEXISTS(semi-join, no dedup).