Query Execution Order
You type SELECT first. The database runs it fifth. Step through the real order and watch the row count change at every stage.
Step Through It
Press Step to run the first stage: FROM.
Try Breaking It
The Query, Written
—The Order It Actually Runs
Rows At This Stage
Row Count
Query Execution Order: A Practical Guide
The one thing that explains every "why can't I do that here" in SQL.
Quick Context
SQL is written in one order and executed in another. You write SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT, top to bottom. The engine runs
FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
Every rule in SQL that feels arbitrary — why WHERE can't use an aggregate, why a SELECT alias works in ORDER BY but not in WHERE — falls straight out of this list once you know where each clause sits in it.
Why the order matters
- WHERE runs before SELECT exists. The alias you defined in SELECT has not been computed yet, so WHERE cannot see it — and cannot see GROUP BY's aggregates either, which is exactly why HAVING exists as a separate clause that runs after grouping.
- ORDER BY runs after SELECT. The alias exists by then, so it is legal there and in LIMIT, but nowhere earlier.
- LIMIT runs dead last. It cuts the final sorted set, which is why LIMIT without ORDER BY returns an arbitrary N rows rather than "the top N" of anything.
Interactive Exploration Guide
- Step through it. Eight rows enter at FROM. WHERE cuts some out, GROUP BY collapses what remains into groups, HAVING cuts groups, and only then does SELECT compute the columns you asked for.
- Try the alias in WHERE. Tick the box and the query is marked invalid — SELECT has not run yet, so the name does not exist.
- Try it in ORDER BY instead. Legal, because ORDER BY runs after SELECT has already computed the alias.
Key Takeaway
SQL executes FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT — not the order you write it in. A clause can only reference what an earlier stage has already produced, which is the single rule behind every "that name doesn't exist here" error SQL ever gives you.