What is the difference between EXISTS and IN?

SQL Server T-SQL Intermediate 2–3 Yrs3–5 Yrs SQL Query 1 min read

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 any y is NULL, the whole predicate becomes UNKNOWN and you get zero rows. NOT EXISTS handles nulls correctly.
  • Performance: for correlated existence checks, modern SQL Server optimises IN, EXISTS and = ANY similarly. EXISTS can be clearer intent and is null-safe.
  • JOIN vs EXISTS: a JOIN that then DISTINCTs to remove duplicates from the right side is often better written as EXISTS (semi-join, no dedup).