Learn SQL/Beginner/SQL Foundations/SQL Query Execution Order

SQL Query Execution Order

You write SELECT first. PostgreSQL runs it fifth. Here is the actual logical order and why it matters.

Written Order vs. Execution Order

SQL reads top to bottom like English, but that is not the order it logically runs. PostgreSQL processes clauses in a fixed sequence regardless of the order in which they appear on the page.

idnamechannelspendstart_dateend_datestatustarget_segment
1Spring Launchgoogle_ads55000.002024-01-152024-03-31activesmb
2Retention Webinaremail45000.002024-02-102024-04-15activeenterprise
3Finance Retargetinglinkedin50000.002024-03-122024-05-31activeenterprise
4Enterprise Searchgoogle_ads60000.002024-04-012024-06-30activeenterprise
EXAMPLE QUERY
SELECT
  channel,
  AVG(spend) AS avg_spend
FROM marketing.campaigns
WHERE status = 'active'
GROUP BY channel
HAVING AVG(spend) > 48000
ORDER BY avg_spend DESC
LIMIT 2;

Watch the query run against Queryflo campaign data. The numbered step shows the clause being evaluated, not the line currently being read.

Watch the execution order runStage 1 of 7
1FROM
2WHERE
3GROUP BY
4HAVING
5SELECT
6ORDER BY
7LIMIT
FROM marketing.campaigns
namechannelspendstatus
Spring Launchgoogle_ads55,000.00active
Retention Webinaremail45,000.00active
Finance Retargetinglinkedin50,000.00active
Enterprise Searchgoogle_ads60,000.00active

FROM loads all four rows from marketing.campaigns before any condition is checked.

Why This Matters

Two consequences follow directly from the logical order:

  • You cannot reference a SELECT alias inside WHERE, because WHERE runs before SELECT creates that alias.
  • You can reference the alias inside ORDER BY, because SELECT has already run by then.
Now You Try

Practice this concept

Marketing wants the two active campaign channels whose average spend is greater than 48,000, ordered from highest to lowest average spend.

Available schema
marketing

Prefix tables with marketing.table_name.

channelavg_spend
marketing.campaigns
ColumnType
idinteger
nametext
channeltext
spendnumeric
start_datedate
end_datedate
statustext
target_segmenttext
legacy_idtext
query.sql
Beginner business practice

Sign up free to try it on a real business scenario