SQL
SQL NOT IN Operator: Syntax, Usage, and Examples
The NOT IN operator filters out rows where a value matches anything in a list or subquery. You use it when you want the opposite of IN, meaning “show me everything except these values.”
How to Use the NOT IN operator
You can use the NOT IN operator inside a WHERE clause. It checks if a column value is not included in a given list.
Learn SQL on Mimo
Basic syntax (with a list of values)
SQL
SELECT column_name
FROM table_name
WHERE column_nameNOTIN (value1, value2, value3);
Syntax (with a subquery)
SQL
SELECT column_name
FROM table_name
WHERE column_nameNOTIN (
SELECT column_name
FROM other_table
WHEREcondition
);
In both cases, the parentheses matter because NOT IN expects a list-like result.
When to Use the NOT IN operator
The NOT IN operator is perfect when you want to exclude a known set of results. Here are a few situations where it really shines.
1) Excluding a list of values
Sometimes you already know which values you don’t want. Maybe you’re filtering out canceled orders, internal test accounts, or certain categories.
Example idea:
- show orders except
"Canceled"and"Refunded" - show users except
"guest"and"anonymous"
2) Filtering out results from another table
You can use NOT IN with a subquery when you want to exclude values found somewhere else.
Common example:
- show customers who haven’t placed an order
- show products that aren’t in the “featured” list
3) Cleaning up reports by removing outliers
For analytics and dashboards, you might remove a few known values that distort the data. For example, internal traffic sources, admin accounts, or demo records.
4) Narrowing down missing relationships
When you work with relational databases, you often want to find “things that don’t have a match.” NOT IN helps answer questions like:
- Which employees are not assigned to a team?
- Which students are not enrolled in any course?
Examples of the NOT IN operator
Let’s walk through a few common examples that you can copy, run, and adapt.
Example 1: Exclude specific categories
You’re building a report and want to ignore categories that aren’t relevant.
SQL
SELECT product_id, product_name, category
FROM products
WHERE categoryNOTIN ('Gift Card','Promo Item');
This returns all products except those in the two excluded categories.
Example 2: Exclude multiple statuses
Imagine an orders table where you only want active orders.
SQL
SELECT order_id, customer_id, status
FROM orders
WHERE statusNOTIN ('Canceled','Refunded','Fraud');
This is a clean way to say “only keep orders that are still valid.”
Example 3: Find customers who never placed an order
You have a customers table and an orders table.
SQL
SELECT customer_id, full_name
FROM customers
WHERE customer_idNOTIN (
SELECT customer_id
FROM orders
);
This finds customers whose customer_id is missing from the orders table.
It’s a classic “who hasn’t done X?” query.
Example 4: Filter using a date-based subquery
Let’s say you want all products that were not purchased during a sale period.
SQL
SELECT product_id, product_name
FROM products
WHERE product_idNOTIN (
SELECT product_id
FROM order_items
WHERE order_dateBETWEEN'2026-01-01'AND'2026-01-07'
);
This can help compare “sale week vs normal week” behavior.
Learn More About the NOT IN operator
The NOT IN operator is simple, but there are a few gotchas that can bite you if you don’t know about them.
NOT IN and NULL values
This is the big one.
If the list (or subquery results) contains NULL, NOT IN can behave in a surprising way. In SQL, comparisons with NULL produce “unknown,” not true or false.
Example problem:
SQL
SELECT customer_id
FROM customers
WHERE customer_idNOTIN (
SELECT customer_id
FROM orders
);
If the orders.customer_id column contains even one NULL, then the subquery result list includes NULL, and the NOT IN comparison may return zero rows.
That can make you stare at your screen like: “I know there are customers without orders. Where did they go?”
How to fix it
Filter out NULL inside the subquery:
SQL
SELECT customer_id, full_name
FROM customers
WHERE customer_idNOTIN (
SELECT customer_id
FROM orders
WHERE customer_idISNOT NULL
);
Now the comparison stays clean.
NOT IN vs NOT EXISTS
Sometimes NOT EXISTS is safer than NOT IN, especially with subqueries that might return NULL.
Here’s the same “customers with no orders” query using NOT EXISTS:
SQL
SELECT c.customer_id, c.full_name
FROM customers c
WHERENOTEXISTS (
SELECT1
FROM orders o
WHERE o.customer_id= c.customer_id
);
Many developers prefer this in production because it avoids the NULL trap and often performs well in real databases.
NOT IN vs <> (not equal)
NOT IN is for excluding multiple values.
<> is for excluding just one value.
Example:
SQL
-- Excluding one status
SELECT*
FROM orders
WHERE status<>'Canceled';
If you need to exclude two or more values, NOT IN becomes the cleaner option:
SQL
SELECT*
FROM orders
WHERE statusNOTIN ('Canceled','Refunded');
Using NOT IN with strings, numbers, and IDs
The NOT IN operator works across data types:
SQL
-- Numbers
WHERE ratingNOTIN (1,2)
-- Strings
WHERE countryNOTIN ('US','CA')
-- IDs
WHERE user_idNOTIN (10,15,22)
Just match the types to the column. Mixing types can cause implicit conversions or errors depending on the database.
A small performance tip
If your list is huge (like hundreds or thousands of values), NOT IN (...) can get messy and slow.
In that case, your best option is often:
- put those values into a table (or temp table)
- join and filter them out cleanly
That’s more scalable than pasting a novel inside parentheses.
Summary
The NOT IN operator helps you filter out rows that match a list of excluded values or a subquery result. Use it for clean reporting, removing unwanted categories, and finding “missing” relationships between tables. Just watch out for NULL values in subqueries, because a single NULL can break the whole filter, and consider NOT EXISTS as a safer alternative in those cases.
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot