SQL IN vs OR: IN and NOT IN Operators
Lists of allowed or excluded values are clearer with IN than repeated OR checks.
When one column can match several values,
IN
keeps the query shorter and easier to scan. It asks whether a value appears
in a list.
NOT IN
excludes values found in the list, but it isn't a perfect logical opposite
when nulls are involved. The null trap is covered below.
SQL IN vs OR
IN and repeated OR checks can mean the same thing
when every comparison is against the same column. Use IN for
that case because it is shorter and makes the list of allowed values
obvious.
-- Repeated OR checks
where state = 'PA'
or state = 'OR'
or state = 'FL'
-- Equivalent IN list
where state in ('PA', 'OR', 'FL') | Pattern | Best when | Example |
|---|---|---|
IN | One column can match several known values. | state in ('PA', 'OR', 'FL') |
OR | Different columns or different kinds of conditions can match. | price > 20 or quantity_on_hand < 10 |
| Parentheses | You mix OR with AND. | (state = 'PA' or state = 'OR') and is_active |
Keep the list short and explicit
IN
is best for a small, known set of values such as states, statuses, or
categories. If the list is coming from another table, a join or subquery
is usually clearer than copying many values into the SQL by hand.
select column_one, column_two
from table_name
where column_name in ('value one', 'value two')
and other_column not in ('value three') Open the DuckDB playground with the matching dataset and query already filled in.
Common mistakes
-
Don't use
INfor unrelated conditions. UseORwhen the alternatives involve different columns. -
Be careful with
NOT INwhen the list or subquery can containNULL. A singleNULLmeansNOT INcan never be true. See why NOT IN with NULL returns nothing. -
When you mix
ANDandOR, add parentheses. See why OR without parentheses changes your filter.
Schema · Garden Shop Table · suppliers 4 columns · 6 rows
One row per supplier. Some suppliers have no contact email.
Show the supplier name and state for suppliers in PA, OR, or FL, leaving out Ironwood Tools, which the shop no longer buys from.
Run your query to inspect the result.
Expected answer
- Columns: supplier_name, state.
- Rows: 3 suppliers.
- RootWorks Supply stays in; Ironwood Tools, the other PA supplier, is excluded.
Related
Comparisons, AND/OR, IN, BETWEEN, and LIKE.
SELECT, WHERE, ORDER BY, and LIMIT at a glance.
Debug filters that match nothing.
Nested SELECTs, IN, EXISTS, and correlation.
UNION, UNION ALL, INTERSECT, and EXCEPT.
A stray NULL drops every row. Use NOT EXISTS.