datarekha
SQL Medium Asked at GoogleAsked at AmazonAsked at MetaAsked at Microsoft

What is the logical processing order of a SQL SELECT statement?

The short answer

SQL processes clauses in this order: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT. This matters because it explains why you cannot use a SELECT alias in a WHERE clause, but you can use it in ORDER BY.

How to think about it

The order you write SQL differs from the order the engine evaluates it. This single mental model resolves almost every “why doesn’t this work?” SQL question — including alias scoping, WHERE vs. HAVING, and the ORDER BY exception.

The logical processing order (LPO)

Why you cannot use a SELECT alias in WHERE

WHERE runs at step 2. The aliases you name in SELECT are not computed until step 5 — they literally do not exist yet.

-- WRONG: alias net_price does not exist when WHERE runs
SELECT price * 0.9 AS net_price
FROM products
WHERE net_price < 50;

-- CORRECT: repeat the expression in WHERE
SELECT price * 0.9 AS net_price
FROM products
WHERE price * 0.9 < 50;

Why you CAN use a SELECT alias in ORDER BY

ORDER BY runs at step 6, after SELECT at step 5 — so aliases are fully computed and available.

-- WORKS: ORDER BY runs after SELECT
SELECT price * 0.9 AS net_price
FROM products
ORDER BY net_price;

Why aggregates work in HAVING but not WHERE

WHERE (step 2) fires before GROUP BY (step 3), so there are no aggregated groups yet. HAVING (step 4) fires after grouping — COUNT(*), SUM(amount), etc. are fully computed by then.

Run this and experiment — try moving the HAVING filter into a WHERE to see the error:

The ORDER BY + LIMIT trap

Note: MySQL and BigQuery allow SELECT aliases in HAVING as a convenience extension. PostgreSQL and SQL Server do not — they follow strict LPO. If portability matters, always use the expression directly.

Learn it properly SELECT basics

Keep practising

All SQL questions

Explore further

Skip to content