SQL WHERE Clause
Most questions you ask a database are about some rows, not all of them: the orders from January, the products that are out of stock, the employees in Pune. The WHERE clause filters rows so that only the ones matching a condition reach the result.
- Filter rows with comparison operators
- Compare numbers, text and dates correctly
- Use
WHEREwithUPDATEandDELETEsafely - Spot the classic WHERE mistakes
WHERE syntax
SELECT column1, column2FROM table_nameWHERE condition;The condition is checked for every row. Rows where it is true are kept; rows where it is false or unknown (because of NULL) are dropped.
Sample data
| product_id | product_name | category | price | stock |
|---|---|---|---|---|
| 1 | Wireless Mouse | Electronics | 799 | 120 |
| 2 | Mechanical Keyboard | Electronics | 3499 | 45 |
| 3 | USB-C Hub | Electronics | 1999 | 0 |
| 4 | Office Chair | Furniture | 8999 | 12 |
| 5 | Standing Desk | Furniture | 18999 | 5 |
| 6 | Notebook Pack | Stationery | 249 | 300 |
| 7 | Gel Pens | Stationery | 199 | 250 |
| 8 | Desk Lamp | Furniture | 1499 | 30 |
| 9 | Monitor Arm | Furniture | 2799 | 18 |
Filter on a number
Which products cost less than 1,000?
SELECT product_name, priceFROM productsWHERE price < 1000;| product_name | price |
|---|---|
| Wireless Mouse | 799 |
| Notebook Pack | 249 |
| Gel Pens | 199 |
FROM productsreads the 9 products.WHERE price < 1000tests each row: 799, 249 and 199 pass; the other six fail.SELECTreturns the name and price of the 3 rows that passed.
Comparison operators
| Operator | Meaning | Example |
|---|---|---|
= | equal | category = 'Furniture' |
<> or != | not equal | status <> 'Delivered' |
> | greater than | price > 2000 |
< | less than | stock < 10 |
>= | greater than or equal | salary >= 100000 |
<= | less than or equal | quantity <= 2 |
Products that are out of stock:
SELECT product_id, product_name, stockFROM productsWHERE stock = 0;| product_id | product_name | stock |
|---|---|---|
| 3 | USB-C Hub | 0 |
Orders that are not delivered yet:
SELECT order_id, customer_id, statusFROM ordersWHERE status <> 'Delivered';| order_id | customer_id | status |
|---|---|---|
| 1004 | 3 | Cancelled |
| 1006 | 5 | Shipped |
| 1008 | 1 | Pending |
<>means “not equal to”.- Seven orders are Delivered, so the other three come back: one Cancelled, one Shipped and one Pending.
Filter on text
Text values go in single quotes. With MySQL’s default collation the comparison ignores case:
SELECT first_name, last_name, cityFROM employeesWHERE city = 'Pune';| first_name | last_name | city |
|---|---|---|
| Priya | Nair | Pune |
| Kavya | Iyer | Pune |
| Rohan | Joshi | Pune |
Filter on dates
Write dates as 'YYYY-MM-DD' text. MySQL compares them as dates, so > means “later than”:
SELECT first_name, hire_dateFROM employeesWHERE hire_date >= '2022-01-01'ORDER BY hire_date;| first_name | hire_date |
|---|---|
| Neha | 2022-03-14 |
| Karan | 2022-08-29 |
| Arjun | 2023-06-05 |
| Rohan | 2024-01-22 |
| Amit | 2025-06-02 |
hire_date >= '2022-01-01'keeps people hired on or after 1 January 2022.- Five employees joined in 2022 or later.
ORDER BY hire_datelists them from the earliest to the latest hire.
Filter on a calculated value
The condition can use expressions. Which order lines are worth more than 5,000?
SELECT oi.order_id, p.product_name, oi.quantity, p.price, oi.quantity * p.price AS line_totalFROM order_items oiJOIN products p ON p.product_id = oi.product_idWHERE oi.quantity * p.price > 5000;| order_id | product_name | quantity | price | line_total |
|---|---|---|---|---|
| 1002 | Office Chair | 1 | 8999 | 8999 |
| 1008 | Office Chair | 2 | 8999 | 17998 |
| 1004 | Standing Desk | 1 | 18999 | 18999 |
- The
JOINpairs each order line with its product so the price is available (INNER JOIN). WHEREcalculatesquantity * pricefor each line and keeps the lines above 5,000.- The alias
line_totalcannot be used inWHERE(it is created later, inSELECT), so the expression is repeated.
WHERE with UPDATE and DELETE
WHERE decides which rows an UPDATE or DELETE touches. Without it, every row changes:
UPDATE productsSET stock = 50WHERE product_id = 3; SELECT product_id, product_name, stock FROM products WHERE product_id = 3;| product_id | product_name | stock |
|---|---|---|
| 3 | USB-C Hub | 50 |
Before running an UPDATE or DELETE, run a SELECT with the same WHERE and check that it returns exactly the rows you mean to change.
Common WHERE mistakes
- Comparing with NULL using
=.WHERE commission = NULLnever matches. UseIS NULL(NULL Values). - Forgetting quotes around text.
WHERE city = Punemakes MySQL look for a column calledPune. - Quoting numbers.
WHERE price < '1000'works, but MySQL has to convert the text first; keep numbers unquoted. - Using a SELECT alias in WHERE.
WHERE line_total > 5000fails, becauseWHEREruns beforeSELECT.
SELECT first_name FROM employees WHERE city = Pune;ERROR 1054 (42S22): Unknown column 'Pune' in 'where clause'
Predict the result
How many rows does this return?
SELECT first_name, salaryFROM employeesWHERE salary <> 72000;| first_name | salary |
|---|---|
| Meera | 250000 |
| Asha | 125000 |
| Rahul | 98000 |
| Vikram | 105000 |
| Neha | 54000 |
| Arjun | 48000 |
| Kavya | 88000 |
| Rohan | 45000 |
| Sneha | 78000 |
| Amit | 25000 |
Ten rows. Priya and Karan both earn exactly 72,000, so they are excluded; all other 10 employees pass the condition.
Exercise: Recent orders
Show order_id, customer_id and order_date for orders placed on or after 1 April 2025.
| order_id | customer_id | order_date |
|---|---|---|
| 1007 | 2 | 2025-04-10 |
| 1008 | 1 | 2025-04-28 |
| 1009 | 3 | 2025-05-15 |
| 1010 | 5 | 2025-06-01 |
Hint 1
Compare order_date with the text '2025-04-01' using >=.
SELECT order_id, customer_id, order_dateFROM ordersWHERE order_date >= '2025-04-01';| order_id | customer_id | order_date |
|---|---|---|
| 1007 | 2 | 2025-04-10 |
| 1008 | 1 | 2025-04-28 |
| 1009 | 3 | 2025-05-15 |
| 1010 | 5 | 2025-06-01 |
Exercise: Furniture under 5,000
List the product_name and price of products in the Furniture category. (Filtering on two conditions at once comes in the next lesson; here, just the category.)
| product_name | price |
|---|---|
| Office Chair | 8999 |
| Standing Desk | 18999 |
| Desk Lamp | 1499 |
| Monitor Arm | 2799 |
Hint 1
WHERE category = 'Furniture'
SELECT product_name, priceFROM productsWHERE category = 'Furniture';| product_name | price |
|---|---|
| Office Chair | 8999 |
| Standing Desk | 18999 |
| Desk Lamp | 1499 |
| Monitor Arm | 2799 |
Quick quiz
1. Which operator means “not equal” in SQL?
<> is standard SQL; MySQL also accepts !=.
2. How should a date be written in a MySQL WHERE clause?
Use the ISO format 'YYYY-MM-DD' in single quotes.
3. What happens to a row when the WHERE condition is unknown because of NULL?
Only rows where the condition is true are returned.
4. What does UPDATE products SET stock = 0; without WHERE do?
Without WHERE, every row is updated.
WHERE clause FAQ
What is the WHERE clause in SQL?
WHERE filters rows. It follows FROM and contains a condition; only rows for which the condition is true are returned, updated or deleted.
Can I use WHERE with GROUP BY?
Yes. WHERE filters rows before they are grouped. To filter the groups themselves, for example “departments with more than 3 employees”, use HAVING.
What is the difference between WHERE and HAVING?
WHERE filters individual rows before grouping and cannot use aggregate functions. HAVING filters groups after GROUP BY and can use aggregates such as COUNT(*).
Is the WHERE clause case sensitive in MySQL?
With the default utf8mb4_0900_ai_ci collation, text comparisons are case and accent insensitive, so 'pune' matches 'Pune'. Use a binary or _cs collation for case-sensitive matching.