Quick Reference
SQL for Builders — Cheat Sheet
Every query pattern from the course, organised by category. Print it, save it, reference it.
Read Data (SELECT)
SELECT * FROM users;Get all columns from the users tableSELECT name, email FROM users;Get specific columns onlySELECT name AS customer FROM users;Rename a column in the result (alias)SELECT COUNT(*) FROM users;Count all rowsSELECT DISTINCT plan FROM users;Get unique values onlyFilter Rows (WHERE)
WHERE plan = 'pro'Exact match — use single quotes for textWHERE amount > 50Greater than — also < >= <=WHERE plan != 'free'Not equal (<> also works)WHERE email LIKE '%@gmail.com'Pattern match — % is wildcardWHERE plan IN ('pro', 'enterprise')Match any value in listWHERE cancelled_at IS NULLColumn has no valueWHERE amount BETWEEN 10 AND 50Inclusive rangeWHERE plan = 'pro' AND amount > 100Both conditions must be trueWHERE plan = 'free' OR plan = 'trial'Either condition trueSort & Limit
ORDER BY created_at DESCNewest first (descending)ORDER BY name ASCA-Z (ascending — default)ORDER BY plan, created_at DESCSort by multiple columnsLIMIT 10Return only 10 rowsLIMIT 10 OFFSET 20Skip 20, then take 10 (page 3)Aggregate Functions
COUNT(*)Count all rows including nullsCOUNT(email)Count non-null values in a columnSUM(amount)Total of a numeric columnAVG(amount)Average valueMAX(amount)Largest valueMIN(amount)Smallest valueGroup Data (GROUP BY)
GROUP BY planGroup rows that share the same plan valueGROUP BY u.id, u.nameGroup by multiple columnsHAVING COUNT(*) > 3Filter groups after aggregationHAVING SUM(amount) > 1000Only groups with total over 1000Join Tables
JOIN users u ON o.user_id = u.idInner join — only matching rowsLEFT JOIN orders o ON o.user_id = u.idAll users, even with no ordersWHERE o.id IS NULLUsed after LEFT JOIN to find unmatched rowsWrite Data (INSERT / UPDATE / DELETE)
INSERT INTO users (name, email) VALUES ('Ama', 'ama@co.com');Add a new rowUPDATE users SET plan = 'pro' WHERE id = 42;Change a specific rowDELETE FROM orders WHERE id = 99;Remove a specific rowQuery anatomy — full example
SELECT u.name, SUM(o.amount) AS total_spend -- 1. What to return FROM users u -- 2. Main table (alias u) JOIN orders o ON o.user_id = u.id -- 3. Join another table WHERE u.plan = 'pro' -- 4. Filter rows AND o.status = 'paid' GROUP BY u.id, u.name -- 5. Group rows HAVING SUM(o.amount) > 100 -- 6. Filter groups ORDER BY total_spend DESC -- 7. Sort LIMIT 10; -- 8. Cap rows returned
SQL processes in this order: FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
Real-world queries every builder needs
Monthly revenue
SELECT SUM(amount) AS mrr
FROM orders
WHERE status = 'paid'
AND created_at >= DATE_TRUNC('month', NOW());New users this week
SELECT COUNT(*) AS new_users FROM users WHERE created_at >= NOW() - INTERVAL '7 days';
Top 10 by spend
SELECT u.name, SUM(o.amount) AS spend FROM users u JOIN orders o ON o.user_id = u.id WHERE o.status = 'paid' GROUP BY u.id, u.name ORDER BY spend DESC LIMIT 10;
Users with 0 orders
SELECT u.name, u.email FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE o.id IS NULL;
Safe write workflow
1.SELECT first — check what you're about to change
2.Add WHERE before UPDATE or DELETE — never skip it
3.LIMIT 10 on big tables before removing LIMIT
4.Test in staging before running on production