WHERE: picking rows
The queries in the last lesson gave back every row in the table. Most of the time you want only some of them: the cheap products, the customers in London, the orders that haven't shipped. That's what WHERE does:
1SELECT name, price2FROM products3WHERE price < 10;
| name | price |
|---|---|
| Notebook | 4.50 |
| Pens (10) | 6.00 |
| USB cable | 8.50 |
| Coffee mug | 9.90 |
Of the 10 products, only these 4 cost less than 10.
How WHERE picks rows
After WHERE comes a condition. The database takes the whole table and looks at it one row at a time: if the condition is true, the row stays; if not, the row is dropped. Only then does SELECT pick the columns to show.
1SELECT name, stock2FROM products3WHERE stock > 50;
| name | stock |
|---|---|
| Notebook | 120 |
| Pens (10) | 80 |
| USB cable | 200 |
| Coffee mug | 60 |
Press Step on this one to see each stage: first the 10 rows that FROM gets, then WHERE marking each row as kept or dropped, and last SELECT keeping only two columns.
The clauses of a query always come in this order: SELECT, FROM, WHERE. By habit each clause starts its own line, which keeps the query easy to read.
Comparisons
These are the comparisons you'll use most in a condition:
| Write | Meaning |
|---|---|
= | equal to |
<> | not equal to |
< > | less than, greater than |
<= >= | less than or equal, greater than or equal |
Note that "equal" in SQL is a single =. Which product is sold out?
1SELECT name, stock2FROM products3WHERE stock = 0;
| name | stock |
|---|---|
| Desk lamp | 0 |
Employees who earn 4000 or more:
1SELECT name, title, salary2FROM employees3WHERE salary >= 4000;
| name | title | salary |
|---|---|---|
| Grace Lee | Manager | 6000 |
| Omar Haddad | Sales lead | 4500 |
| Lucia Romero | Warehouse lead | 4200 |
Tip: MySQL also accepts !=, which means the same as <>. <> is the standard way to write it and works in every database.
How many rows does the result have?
1SELECT name, price2FROM products3WHERE price >= 15;
The products priced 39.90, 59.00, 25.00 and 15.00 all stay. The phone case costs exactly 15.00, and >= includes equal, so it counts too.
Text needs quotes
Numbers are written as they are; text (also called a string) goes in single quotes. Which orders haven't shipped yet?
1SELECT id, customer_id, status2FROM orders3WHERE status = 'pending';
| id | customer_id | status |
|---|---|---|
| 7 | 2 | pending |
| 9 | 1 | pending |
| 12 | 4 | pending |
Not equal works the same way. Every order except the shipped ones:
1SELECT id, status2FROM orders3WHERE status <> 'shipped';
| id | status |
|---|---|
| 4 | cancelled |
| 7 | pending |
| 9 | pending |
| 12 | pending |
Forget the quotes and you get an error:
1SELECT name2FROM customers3WHERE city = London;
ERROR 1054 (42S22): Unknown column 'London' in 'where clause'
Without quotes, the database takes London for a column name, and the table has no such column, so it says it doesn't know a column called London. Write 'London' and it works.
Text has to match exactly: 'London UK' finds no rows. That isn't an error; the result is just empty. By default MySQL ignores the case of letters ('london' and 'London' count as equal); other databases may not.
Dates
Dates go in quotes too, written as 'year-month-day', like '2025-07-01'. Comparing dates means comparing earlier and later: the later date is the "bigger" one. Customers who joined on or after July 1:
1SELECT name, joined2FROM customers3WHERE joined >= '2025-07-01';
| name | joined |
|---|---|
| Hana Sato | 2025-07-21 |
| Ivan Petrov | 2025-08-30 |
| Julia Costa | 2025-09-14 |
Orders from before September 20:
1SELECT id, order_date2FROM orders3WHERE order_date < '2025-09-20';
| id | order_date |
|---|---|
| 1 | 2025-09-02 |
| 2 | 2025-09-05 |
| 3 | 2025-09-18 |
The condition's columns needn't be selected
A column used in WHERE doesn't have to appear after SELECT. This query picks products by category, yet shows only their names:
1SELECT name2FROM products3WHERE category = 'Kitchen';
| name |
|---|
| Water bottle |
| Coffee mug |
Practice
Write the query, then press Check. A hint costs nothing; the answer is there when you need it.
Pricey products
✓Get the products that cost more than 20, with two columns: name and price.
| name | price |
|---|---|
| Backpack | 39.90 |
| Headphones | 59.00 |
| Desk lamp | 25.00 |
1SELECT name, price2FROM products;
Fix it: the quotes
✓This query should get the name and email of the customers in Paris, but it gives an error. Fix it.
| name | |
|---|---|
| Ben Okafor | [email protected] |
| Farah Khan | NULL |
1SELECT name, email2FROM customers3WHERE city = Paris;
October orders
✓Get the orders from October 1, 2025 on (that day included), with two columns: id and order_date.
| id | order_date |
|---|---|
| 5 | 2025-10-01 |
| 6 | 2025-10-03 |
| 7 | 2025-10-10 |
| 8 | 2025-10-12 |
| 9 | 2025-10-15 |
| 10 | 2025-10-20 |
| 11 | 2025-10-22 |
| 12 | 2025-10-25 |
1SELECT id, order_date2FROM orders;
What you learned
WHERE conditionkeeps only the rows where the condition is true; the clauses goSELECT,FROM,WHERE.- Compare with
=,<>,<,>,<=,>=; equal is a single=. - Text and dates go in single quotes; text without quotes is taken for a column name and gives
ERROR 1054. - Dates are written
'year-month-day', and comparing them means earlier and later. - A column used in
WHEREdoesn't have to be inSELECT.