SQL Coding · Cheat Sheet
Reading the Query
Cheatsheet: Reading the Query
One page for Topic 1. When a query lands on your desk, work down this page top to bottom.
Processing order (memorize this)
SQL is written SELECT-first but processed FROM-first. Read it the way the database runs it:
| Step | Clause | Question it answers |
|---|---|---|
| 1 | FROM | Which table(s) is this pulling from? |
| 2 | WHERE | Which rows survive before anything is counted or summed? |
| 3 | SELECT | Of the surviving rows, what is actually returned or calculated? |
Jumping to FROM first — not reading top to bottom — is the single habit that makes queries stop feeling like a wall of text.
Alias honesty
AS renames an output column. It changes no data — it's a label the author chose.
| What you see | What it actually computes | Verdict |
|---|---|---|
SUM(order_total) AS total_spent | Sum of order totals | Honest |
COUNT(DISTINCT session_id) AS total_users | Count of sessions | Lying alias — verify the expression, not the name |
... AS conversion_rate | Arithmetic done on the fly | A formula wearing a friendly name — only as trustworthy as the math next to it |
Two rules:
- Calculated columns (sums, counts, ratios) exist only in this query's output — they are not facts stored in a table.
- The fastest way to catch a misleading dashboard number: check whether the alias matches what's being computed.
WHERE operators
| Operator | Meaning | Gotcha |
|---|---|---|
= | Equals | — |
!= or <> | Not equal | Silently excludes NULL rows — "not US" drops unknown-country rows too |
BETWEEN 10 AND 20 | 10 ≤ x ≤ 20 | Inclusive on both ends |
IN ('A','B','C') | Shorthand for chained OR equalities | Same precedence risk as OR when mixed with AND |
AND | Both conditions must be true | Evaluated before OR |
OR | Either condition suffices | Usually returns far more rows than intended if misplaced |
AND/OR precedence — the parentheses rule
SQL evaluates AND before OR. "CA or NY customers who spent over $500":
-- Correct
WHERE (state = 'CA' OR state = 'NY') AND total_spent > 500
-- Wrong: means "ALL CA customers, plus NY customers over $500"
WHERE state = 'CA' OR state = 'NY' AND total_spent > 500
Rule: if a WHERE mixes OR and AND without parentheses, don't trust your first reading — rewrite it with explicit parentheses to see what it actually does. Nothing errors; it just returns a plausible-looking wrong number.
Join types — which rows survive
Two tables: customers (one row per customer) and orders (many or zero per customer).
| Join type | Customer with 0 orders | Customer with 3 orders | Use when |
|---|---|---|---|
| INNER JOIN | Disappears entirely | Appears 3 times | Only matched rows matter |
| LEFT JOIN | Appears once, order columns NULL | Appears 3 times | The query claims to show "all" of the left table |
| RIGHT JOIN | Mirror of LEFT | Mirror of LEFT | Rare — rewrite as LEFT by swapping table order |
"All"/"every" rule: any query whose stated purpose includes "all customers" / "every campaign" needs a LEFT JOIN from that table. An INNER JOIN silently drops the no-match rows and understates the count — the join type, not the WHERE clause, is the first thing to verify.
The multiplication trap
Joining two "many" tables per key creates every combination:
| Customer has | Result rows |
|---|---|
| 3 orders, 2 addresses (both joined) | 3 × 2 = 6 rows, not 5 |
Any SUM() taken after a row-multiplying join is silently inflated — this is the most common inflated-revenue bug in real dashboards and in AI-generated "summary" queries.
The row-count habit
Before trusting any query with a JOIN, ask:
- How many rows should this reasonably return? (One per customer? One per order? One per day?)
- Does the join type match that expectation?
- Did any join multiply rows before an aggregate was taken?
Traps
- Reading SELECT before FROM — you form a guess before you know what table it pulls from.
- Trusting the alias over the expression (
AS total_userson a session count). - OR mixed with AND without parentheses — AND binds first; the query silently includes the wrong rows.
!=treated as if it catches "unknown" — it drops NULL rows instead.- INNER JOIN on a query that claims to show "all X" — non-matching rows vanish.
SUM()after joining two many-per-key tables — the join multiplied rows first.- Trusting the plain-English explanation over the code — when they disagree, the code is ground truth.
Aligned to the PostgreSQL documentation and standard SQL semantics.
Make this cheat sheet yours
Personalize this sheet — focus it however you study, or build one from the exact questions you keep getting wrong.