WHERE, operators & the NULL trap
WHERE is where queries get useful — it keeps only the rows you care about. This lesson covers the full filtering toolkit, and the one value that breaks every beginner's intuition: NULL.
Comparison and logical operators
SELECT * FROM products WHERE price > 500;
SELECT * FROM orders WHERE status = 'paid';
SELECT * FROM orders WHERE status != 'cancelled'; -- or <>
-- combine with AND / OR (AND binds tighter than OR — use parens!)
SELECT * FROM products
WHERE category = 'books' AND price < 300;
SELECT * FROM orders
WHERE (status = 'paid' OR status = 'shipped') AND total > 1000;Note strings use single quotes ('paid'). Double quotes mean an identifier (a column name), not a string — a frequent early mistake.
The convenience operators
-- IN — match any of a list (cleaner than chained ORs)
SELECT * FROM orders WHERE status IN ('paid', 'shipped', 'delivered');
-- BETWEEN — inclusive range on both ends
SELECT * FROM products WHERE price BETWEEN 200 AND 500; -- 200 and 500 included
-- LIKE — pattern matching: % = any chars, _ = one char
SELECT * FROM customers WHERE name LIKE 'A%'; -- starts with A
SELECT * FROM customers WHERE name LIKE '%son'; -- ends with son
SELECT * FROM customers WHERE name ILIKE 'a%'; -- ILIKE = case-insensitive (Postgres)NULL: the absence of a value
NULL means "unknown / no value" — and it is not equal to anything, not even another NULL. This is the single biggest SQL gotcha:
SELECT * FROM orders WHERE total = NULL; -- WRONG: returns nothing, ever
SELECT * FROM orders WHERE total IS NULL; -- RIGHT
SELECT * FROM orders WHERE total IS NOT NULL; -- RIGHTAny comparison with NULL yields NULL (not TRUE), so the row is dropped. Because of this, WHERE status != 'paid' silently excludes rows where status is NULL — you often need WHERE status != 'paid' OR status IS NULL.
Burn this in: use IS NULL / IS NOT NULL, never = NULL. And remember that NULL quietly disappears from != filters. Handling nulls correctly is what separates queries that look right from queries that are right. COALESCE(total, 0) substitutes a default when a value might be null.