SQL Execution Order

6.The Language Has Rules Too

M

In this chapter

We'll uncover the real order SQL runs a query in — FROM, WHERE, SELECT, then ORDER BY — and the exact reason a SELECT alias works in ORDER BY but breaks in WHERE.

12–15 min

The Problem in Real Life

Sarah writes what looks like a clean, obvious query: pull each customer's balance under an alias, filter it down to just the ones who owe something, sort the biggest first. She runs it. It breaks — on the WHERE line, on the exact alias she just typed two lines above it.

Mike watches her stare at the screen. She didn't misspell anything. The alias is sitting right there, in the SELECT line, in plain sight. WHERE insists it doesn't exist.

S

Debt doesn't exist yet? I just typed it right there.

Sarah

The Order You Write It vs. The Order It Actually Runs

Written order isn't run order

SQL reads top to bottom on the page, but that's not the sequence it actually executes in.

An alias can vanish depending on where it's used

The exact same AS alias works perfectly in ORDER BY and fails outright in WHERE.

"Unknown column" doesn't always mean a typo

A perfectly spelled alias can still fail if it's referenced before SELECT has actually created it.

Aggregates hit the same wall

A computed total can't be filtered by WHERE either — it doesn't exist yet at that point in the sequence.

What Order Does SQL Actually Run In?

Every query so far has been written top to bottom: SELECT, then FROM, then WHERE, then ORDER BY. That's the order Sarah types it in. It is not the order SQL actually runs it.

SQL evaluates a query in a completely different sequence, called its logical execution order. FROM decides which table's rows are even in play. WHERE filters those rows down. SELECT then decides which columns — and which aliases — actually get created. ORDER BY runs last of all, sorting whatever SELECT already produced.

SQL's Real Execution Order

FROM

Pick the starting table

then

WHERE

Filter rows — no aliases exist yet

then

SELECT

Create the output columns and aliases

then

ORDER BY

Sort whatever SELECT already produced

WHERE runs before SELECT — so an alias like AS Debt, created inside SELECT, doesn't exist yet at the point WHERE is evaluated.

The Query That Looks Fine and Isn't
SELECT BalanceDue AS Debt
FROM Customers
WHERE Debt > 0;

This fails. WHERE runs before SELECT, so the alias Debt doesn't exist yet at the point WHERE is evaluated — the error isn't a typo, it's the execution order.

ORDER BY runs last of all, after SELECT — which is exactly why it's allowed to sort by an alias WHERE could never see.

The Same Alias, Used Where It's Actually Allowed
SELECT BalanceDue AS Debt
FROM Customers
ORDER BY Debt DESC;

This works. ORDER BY runs after SELECT, so by the time sorting happens, Debt already exists.

FROM decides which table's real column names are in play from the start — WHERE has to reference one of those real names, not an alias SELECT hasn't created yet.

The Fix: Repeat the Real Column Name in WHERE
SELECT BalanceDue AS Debt
FROM Customers
WHERE BalanceDue > 0
ORDER BY Debt DESC;

WHERE has to reference the real column name, BalanceDue — not the alias created later. ORDER BY, running after SELECT, is free to use either one.

The same rule applies to an aggregate's result: TotalCustomers doesn't exist until SELECT runs, so WHERE can't filter on it either — that's exactly what HAVING exists for, coming in Act 3.

Why an Aggregate Can't Be Filtered by WHERE Either
SELECT COUNT(*) AS TotalCustomers
FROM Customers
WHERE TotalCustomers > 5;

Fails for the same reason — TotalCustomers doesn't exist until SELECT runs, and WHERE has already finished by then. Filtering on an aggregate's result needs a different clause entirely: HAVING, which runs after aggregation — coming in Act 3.

Notice the pattern across all four queries: anything computed inside SELECT — a plain alias or an aggregate's result — doesn't exist yet by the time WHERE runs. ORDER BY, sitting after SELECT in the real execution order, is the only clause among these four allowed to reference it.

This is why the order Sarah types a query in was never the real story. SQL reads top to bottom, but it runs FROM, then WHERE, then SELECT, then ORDER BY — and once GROUP BY and HAVING join that sequence in Act 3, this exact same rule is what explains where they have to sit.

Key Takeaway

SQL is written SELECT-first, but runs FROM, then WHERE, then SELECT, then ORDER BY — which is exactly why a SELECT alias is invisible to WHERE but visible to ORDER BY.

Why This Matters

Every strange "unknown column" error from here forward traces back to this same rule — a query that looks obviously correct can still fail, not from bad syntax, but because something referenced in one clause simply doesn't exist yet at the point that clause runs. Understanding the real execution order turns those errors from mysterious into predictable.

GreenMart's queries finally make sense not just as sentences, but as a real sequence of steps. This closes out everything queries can do against a single table — the checkpoint next is where Mike gets to answer his own real questions, from scratch.

Next