Data Analyst & Analytics Interview · SQL for Analysts · Lesson 3 of 3
Common query patterns
A handful of shapes recur across nearly every SQL interview. Recognizing the pattern behind a word problem is most of the battle.
- Filter then aggregate:
WHERE(row filter) runs beforeGROUP BY;HAVINGfilters after aggregation (e.g. groups withCOUNT(*) > 5). - Deduplication:
ROW_NUMBER()partitioned by the key, keeprn = 1. - Self-join: compare rows in one table to each other (manager/employee, pairs, gaps).
- Conditional aggregation:
SUM(CASE WHEN ... THEN 1 ELSE 0 END)to pivot categories into columns. - Date bucketing:
DATE_TRUNC('month', ts)to roll events up to a period.
-- Monthly active users and paid share, one row per month SELECT DATE_TRUNC('month', event_ts) AS month, COUNT(DISTINCT user_id) AS mau, COUNT(DISTINCT CASE WHEN plan = 'paid' THEN user_id END) AS paid_mau FROM events GROUP BY 1 HAVING COUNT(DISTINCT user_id) > 100 ORDER BY 1;
Say the order of operationsLogical evaluation order is FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. Reciting it explains why you can't use a SELECT alias in WHERE, and why HAVING (not WHERE) filters aggregates.
NULLs break equality
NULL = NULL is not true — it is unknown. Use IS NULL, and remember NOT IN (subquery) returns no rows if the subquery contains a single NULL. Prefer NOT EXISTS.◆ Lock it in
WHEREfilters rows before grouping;HAVINGfilters groups after.- Conditional aggregation (
SUM(CASE WHEN...)) pivots categories into columns. - Know the logical order of operations and NULL gotchas (
NOT INvsNOT EXISTS).
Feynman drill — say it out loudExplain why you can't reference a SELECT alias in the WHERE clause, using the logical order of operations.
Step 1 rate your confidence · Step 2 pick your answer
You want only months where distinct users exceed 100. Which clause enforces that?
Step 1 — how sure are you?