MySQL IN
Match values against a list of options
📋 What is the IN Operator?
The IN operator checks if a value matches any value in a list. It's a cleaner alternative to multiple OR conditions, making queries more readable and efficient when filtering by multiple specific values.
-- Find customers in specific cities
SELECT * FROM customers
WHERE city IN ('New York', 'Los Angeles', 'Chicago');
-- Same as: city = 'New York' OR city = 'Los Angeles' OR city = 'Chicago'
Key IN Concepts
IN Operator
Match any value in list
WHERE status IN
('active', 'pending')
NOT IN
Exclude values in list
WHERE status NOT IN
('deleted', 'banned')
Numeric Values
Works with numbers
WHERE id IN
(1, 5, 10, 15)
Subquery
Use query results as list
WHERE id IN
(SELECT customer_id
FROM orders)
🔹 Basic IN Syntax
The IN operator simplifies queries that would otherwise require multiple OR conditions. It checks if a column value matches any value in a specified list. This makes your SQL more concise, readable, and easier to maintain than chaining OR statements.
-- Basic syntax
SELECT column_name
FROM table_name
WHERE column_name IN (value1, value2, value3);
-- Example with cities
SELECT name, city, country
FROM customers
WHERE city IN ('Paris', 'London', 'Berlin');
-- Example with numbers
SELECT product_name, category_id
FROM products
WHERE category_id IN (1, 3, 5, 7);
Output:
| name | city | country |
|---|---|---|
| Jean Dupont | Paris | France |
| John Smith | London | UK |
🔹 IN vs Multiple OR
The IN operator is a shorthand for multiple OR conditions. Both produce the same results, but IN is cleaner, more readable, and less prone to errors. It's especially beneficial when you have many values to check against, reducing code complexity significantly.
-- Using multiple OR (verbose)
SELECT * FROM products
WHERE category = 'Electronics'
OR category = 'Computers'
OR category = 'Phones'
OR category = 'Tablets';
-- Using IN (cleaner)
SELECT * FROM products
WHERE category IN ('Electronics', 'Computers', 'Phones', 'Tablets');
-- Both queries return the same results
-- IN is more readable and maintainable
Benefits of IN:
- More concise and readable code
- Easier to add or remove values
- Less chance of syntax errors
- Better performance in some cases
🔹 IN with Text Values
Use IN with string values to filter by multiple text options. Enclose each text value in quotes and separate them with commas. This is perfect for filtering by status, category, name, or any text-based criteria where you need to match several specific values.
-- Filter by multiple statuses
SELECT order_id, customer_name, status
FROM orders
WHERE status IN ('pending', 'processing', 'shipped');
-- Filter by employee departments
SELECT name, department, salary
FROM employees
WHERE department IN ('Sales', 'Marketing', 'IT');
-- Filter by product names
SELECT * FROM products
WHERE product_name IN ('Laptop', 'Mouse', 'Keyboard', 'Monitor');
-- Filter by country codes
SELECT * FROM customers
WHERE country_code IN ('US', 'CA', 'UK', 'AU');
Output (Order Status):
| order_id | customer_name | status |
|---|---|---|
| 101 | John Doe | pending |
| 102 | Jane Smith | processing |
🔹 IN with Numeric Values
IN works seamlessly with numbers, IDs, and numeric codes. No quotes needed for numeric values. This is commonly used for filtering by specific IDs, category numbers, price points, or any numeric identifiers when you need to match multiple specific numbers.
-- Filter by specific IDs
SELECT * FROM customers
WHERE customer_id IN (1, 5, 10, 15, 20);
-- Filter by category IDs
SELECT product_name, price
FROM products
WHERE category_id IN (2, 4, 6);
-- Filter by specific years
SELECT * FROM orders
WHERE YEAR(order_date) IN (2022, 2023, 2024);
-- Filter by price points
SELECT * FROM products
WHERE price IN (9.99, 19.99, 29.99, 49.99);
Output (Specific IDs):
| customer_id | name |
|---|---|
| 1 | Alice Johnson |
| 5 | Bob Wilson |
🔹 NOT IN Operator
NOT IN excludes rows where the column value matches any value in the list. It's the opposite of IN, useful for filtering out unwanted data like inactive users, deleted records, or specific categories you want to exclude from your results.
-- Exclude specific statuses
SELECT * FROM orders
WHERE status NOT IN ('cancelled', 'refunded', 'deleted');
-- Exclude specific departments
SELECT name, department, salary
FROM employees
WHERE department NOT IN ('Intern', 'Contractor');
-- Exclude specific IDs
SELECT * FROM products
WHERE product_id NOT IN (5, 10, 15);
-- Exclude test accounts
SELECT * FROM users
WHERE username NOT IN ('test', 'admin', 'demo');
Output (Exclude Statuses):
| order_id | status |
|---|---|
| 101 | completed |
| 102 | shipped |
🔹 IN with Subquery
Use a subquery inside IN to dynamically generate the list of values from another table. This is powerful for finding related records, such as customers who have placed orders, products that have been sold, or users who have performed specific actions.
-- Find customers who have placed orders
SELECT name, email
FROM customers
WHERE customer_id IN (
SELECT DISTINCT customer_id
FROM orders
);
-- Find products that have been sold
SELECT product_name, price
FROM products
WHERE product_id IN (
SELECT product_id
FROM order_items
);
-- Find employees in departments with > 10 people
SELECT name, department
FROM employees
WHERE department IN (
SELECT department
FROM employees
GROUP BY department
HAVING COUNT(*) > 10
);
-- Find users who commented today
SELECT username, email
FROM users
WHERE user_id IN (
SELECT user_id
FROM comments
WHERE DATE(created_at) = CURDATE()
);
🔹 Combining IN with Other Conditions
Combine IN with other WHERE conditions using AND and OR for complex filtering. This allows you to create sophisticated queries that filter by multiple criteria simultaneously, giving you precise control over which records are returned from your database.
-- IN with AND condition
SELECT * FROM products
WHERE category IN ('Electronics', 'Computers')
AND price < 1000
AND stock_quantity > 0;
-- IN with OR condition
SELECT * FROM customers
WHERE city IN ('New York', 'Los Angeles')
OR country IN ('Canada', 'Mexico');
-- Multiple IN conditions
SELECT * FROM orders
WHERE status IN ('pending', 'processing')
AND customer_id IN (1, 5, 10, 15)
AND YEAR(order_date) IN (2023, 2024);
-- IN with LIKE
SELECT * FROM products
WHERE category IN ('Electronics', 'Computers')
AND product_name LIKE '%Pro%';
🔹 Practical Examples
Real-world applications of the IN operator in common database scenarios:
-- E-commerce: Active orders in specific statuses
SELECT
order_id,
customer_name,
total_amount,
status
FROM orders
WHERE status IN ('pending', 'processing', 'shipped')
AND order_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
ORDER BY order_date DESC;
-- HR: Employees in specific roles
SELECT
employee_id,
name,
position,
salary
FROM employees
WHERE position IN ('Manager', 'Senior Developer', 'Team Lead')
AND department IN ('IT', 'Engineering')
ORDER BY salary DESC;
-- Content: Published posts in categories
SELECT
title,
author,
category,
published_date
FROM blog_posts
WHERE category IN ('Technology', 'Programming', 'Database')
AND status = 'published'
AND published_date >= '2024-01-01'
ORDER BY published_date DESC;
-- Analytics: Users from specific countries
SELECT
user_id,
username,
country,
signup_date
FROM users
WHERE country IN ('US', 'UK', 'CA', 'AU')
AND account_type IN ('premium', 'enterprise')
AND is_active = 1;