The WHERE clause is where a query stops returning everything and starts returning what you asked for. It attaches a condition to your SELECT, and only the rows that make that condition true come back. Master it and you can pull precisely the slice of data you need — everything else in SQL filtering builds on it.
This guide is hands-on: the playground below is a real SQL engine running in your browser against a small sample database. Edit the condition, press Run, and watch the result set shrink and grow. Nothing is sent anywhere.
Try it — change the condition
Sample tables you can query
Quick answer: what does WHERE do?
WHERE filters rows. It sits after the FROM table and keeps only the rows for which its condition is true:
SELECT column1, column2
FROM table_name
WHERE condition;If you omit WHERE, you get every row. Add a condition and the database evaluates it once per row, keeping the matches.
Comparison operators
The simplest conditions compare a column to a value. SQL gives you six comparison operators:
| Operator | Meaning |
|---|---|
= | equal to |
<> (or !=) | not equal to |
< | less than |
> | greater than |
<= | less than or equal to |
>= | greater than or equal to |
SELECT name, price
FROM products
WHERE price <= 25;Numbers compare numerically; text compares alphabetically; dates stored as YYYY-MM-DD compare chronologically. One gotcha: quote values to match the column’s type — price >= 20 (number) but city = 'London' (text). Run the comparisons yourself:
Comparison operators
Sample tables you can query
Combining conditions with AND, OR, and NOT
Real filters usually have more than one condition. The logical operators AND, OR, and NOT join them:
AND— every condition must be true.OR— at least one condition must be true.NOT— flips a condition.
The catch that bites everyone: AND binds tighter than OR. So a OR b AND c means a OR (b AND c), which is probably not what you meant. When you mix them, use parentheses to say exactly what you want:
-- Without parens: OR-group is NOT protected
SELECT * FROM orders
WHERE status = 'shipped' OR status = 'pending' AND amount > 40;
-- With parens: the intended "either status, and over $40"
SELECT * FROM orders
WHERE (status = 'shipped' OR status = 'pending') AND amount > 40;Run both in the playground and compare the row counts — the parentheses change the answer:
AND / OR and the parentheses trap
Sample tables you can query
Filtering shortcuts: IN, BETWEEN, and LIKE
Some conditions come up so often they have dedicated operators. Each has its own deep-dive, but here’s how they fit in a WHERE clause:
IN— match a column against a list of values, instead of chainingORs:WHERE city IN ('New York', 'London').BETWEEN— an inclusive range, instead of>=and<=:WHERE price BETWEEN 20 AND 50.LIKE— pattern matching with%(any characters) and_(one character):WHERE name LIKE 'W%'.
SELECT *
FROM products
WHERE category IN ('Electronics', 'Home')
AND price BETWEEN 20 AND 50;The one that trips everyone up: NULL
NULL means “unknown,” and it does not behave like a value. WHERE price = NULL returns nothing — not even the rows where price actually is null — because a comparison with NULL yields UNKNOWN, never true. To test for missing data you need the dedicated operators IS NULL and IS NOT NULL:
SELECT id, name, segment
FROM customers
WHERE segment IS NULL;IS NULL vs = NULL
Sample tables you can query
Run = NULL and you get zero rows; IS NULL finds the customer with no segment. Same idea applies inside NOT IN lists — a NULL there silently drops every row, a trap covered in the IN operator guide.
Practice
Type a wrong answer and the check tells you how far off you are; hints are one click away. It all runs in your browser.
Return every product that costs between $20 and $50, inclusive. Select name and price.
Sample tables you can query
The clearance team wants products that are either under $20 OR out of stock (in_stock = 0). Return name, price, and in_stock.
Sample tables you can query
Frequently asked questions
What is the WHERE clause in SQL? It filters rows: SELECT ... FROM ... WHERE condition returns only the rows for which the condition is true. Without it, the query returns every row.
How do I use multiple conditions in a WHERE clause? Join them with AND (all must be true) or OR (any must be true), and wrap OR groups in parentheses because AND is evaluated first: WHERE (a OR b) AND c.
Why does WHERE column = NULL return nothing? Comparing anything to NULL yields UNKNOWN, never true. Use IS NULL / IS NOT NULL to test for missing values.
How do I filter text case-insensitively? Normalize both sides with UPPER() / LOWER() — WHERE LOWER(city) = 'london' — or use ILIKE (PostgreSQL). Default case sensitivity varies by database and collation.
What’s the difference between WHERE and HAVING? WHERE filters individual rows before grouping; HAVING filters groups after GROUP BY aggregates them.
From one clause to a whole pipeline
A WHERE clause filters one query. The real work is doing it across many sources, on a schedule, without hand-maintaining SQL scripts. That’s what we built ET1 for — a visual, asynchronous ETL tool where this exact filter is a Filter node you drop onto a canvas, pointed at a CSV, a Postgres table, or an API, with a live preview of the rows passing through.
Ready for the next building block? Filter against a list with the IN operator, match ranges with BETWEEN, or match patterns with LIKE.