Advertisement
When writing queries in SQL, sometimes what you don’t want is just as important as what you do. That’s where the NOT IN operator comes into play. It filters results by excluding certain values from a dataset. Simple enough, right? Well, not always. Although NOT IN feels like an easy tool at first glance, there are hidden quirks you should know about before using it in your projects.
Let’s walk through what NOT IN does, where it can trip you up, and how to use it the right way.
At its core, NOT IN is a way to filter out rows where a column’s value matches anything from a list you provide. Here’s what a basic example looks like:
sql
CopyEdit
SELECT name
FROM employees
WHERE department_id NOT IN (2, 5, 8);
This query says: "Give me all employee names where the department ID is not 2, 5, or 8." Pretty straightforward. The database checks each row’s department_id, and if it’s not one of those numbers, it includes that row in the result.
You can use NOT IN with numbers, text, dates—you name it. As long as the types match between the column and the list, it works the same way.
Here’s where things start to get tricky. NOT IN looks harmless but can behave in ways that surprise a lot of developers. Let’s look at a few situations you’ll want to avoid.
One big issue with NOT IN is how it handles NULL. Imagine running this query:
sql
CopyEdit
SELECT product_name
FROM products
WHERE category_id NOT IN (1, 2, NULL);
At first, you might think it will return all products that aren't in categories 1 or 2. But that’s not what happens. Because NULL means "unknown," SQL doesn’t know whether any given category_id is equal to NULL. So instead of returning rows, you might get an empty result—even when you shouldn’t.
Whenever NULL is involved, NOT IN won’t behave like a regular exclusion. It treats the whole comparison as uncertain, and uncertain in SQL often means "no result."
Another issue pops up when the values in your NOT IN list are a different type than the column you’re checking against. Let’s say your user_id column is an integer, but you accidentally write:
sql
CopyEdit
WHERE user_id NOT IN ('10', '20', '30');
Depending on your database settings, it might try to cast the strings into numbers, or it might just fail. Either way, mismatched types make the query harder to read and can cause unexpected bugs.
If you throw a huge list into NOT IN, performance can drag. SQL has to check each row against every single value in your list. If that list has hundreds (or thousands) of items, things can slow down fast.
While small lists are fine, big ones might be better handled by using a different approach, which we’ll cover next.
Now that you know where NOT IN can cause problems, here are a few ways to keep your queries clean and reliable.
Before you use NOT IN, it’s smart to make sure that the column you’re checking doesn’t have any NULL values. One way to do this is by adding a simple extra condition:
sql
CopyEdit
SELECT order_id
FROM orders
WHERE customer_id IS NOT NULL
AND customer_id NOT IN (101, 102, 103);
By adding customer_id, which is NOT NULL, you guarantee that NOT IN works as expected. It's a small step that avoids a big headache.
If your list of exclusions comes from a subquery, it’s often better to use NOT EXISTS instead of NOT IN. Here’s why: NOT EXISTS doesn’t care about NULL the same way NOT IN does.
Example:
sql
CopyEdit
SELECT e.employee_id
FROM employees e
WHERE NOT EXISTS (
SELECT 1
FROM retired_employees r
WHERE r.employee_id = e.employee_id
);
This way, you're checking directly whether a match exists, not relying on comparing against a list. It's cleaner, more predictable, and usually faster, too.
If you have a long list of values, consider creating a temporary table instead of cramming everything into your query. Then you can just join against that table.
sql
CopyEdit
SELECT product_id
FROM products
WHERE product_id NOT IN (
SELECT product_id
FROM discontinued_products
);
This method is easier to maintain and doesn’t clutter your main query with a wall of numbers or text strings.
Double-check that the values inside your NOT IN list match the type of the column you’re filtering. If the column is an integer, the list should have integers too. It keeps things predictable and avoids random casting issues.
While NOT IN can be quick for small, controlled lists, it's not always the right tool for the job. If your dataset includes lots of NULLs or if the list is dynamically generated and might change often, it’s worth reconsidering.
Use NOT EXISTS if you’re working with subqueries. Use explicit joins if you’re filtering based on big external lists. And always remember: once NULL enters the picture, NOT IN behaves differently than you might expect.
The SQL NOT IN operator is a handy tool, but it needs careful handling. As long as you know about the pitfalls—especially how it treats NULL—you can use it safely. Stick to good practices like filtering out NULLs, matching data types, and keeping your lists reasonable, and your queries will stay fast, clear, and reliable.
If you ever feel unsure whether NOT IN is the right fit for a particular case, step back and think about what's happening behind the scenes. Sometimes, a different approach will save you time, confusion, and maybe even a few bugs down the line.
Advertisement
Looking to boost your SEO in WordPress? Discover 10 AI-powered tools and strategies to improve your content, keyword research, image optimization, and more in 2025.
Want robots that understand natural language? Discover LeRobot by Hugging Face—an open-source library connecting AI models with real-world robotics systems
Learn why FraudGPT is a growing cyber threat and follow 10 essential steps to protect your personal and business data.
ROI, task performance, fidelity, personality, safety, accuracy, and inference speed are the most important GenAI value metrics
Discover how ChatGPT helps build efficient workflows by improving focus, automating tasks, and enhancing clarity.
Need AI built for healthcare, not general use? Aloe offers focused, open medical language models designed for clinical tasks, documentation, research, and patient support
Explore the growing popularity of AI chatbots and their role in delivering faster, smarter support to users everywhere.
Compare Claude and ChatGPT on task handling, speed, features, and integration to find the best AI for daily use.
What is Apple’s MM1 AI, and how will it change Siri and your device experience? Learn how MM1 is designed to bring intelligent, on-device AI to Apple products
Discover 8 AI tools every content writer should use to save time, improve quality, and streamline content creation tasks.
SQL doesn’t behave like Python or JavaScript, so is it a true programming language? Or just a scripting tool? Here’s a clear, human take on what SQL really is—and why it matters
Discover 7 questions and requests that ChatGPT is unable to answer due to privacy rules, ethics, or tech limitations.