SQL Querying

Logical Query Processing

A SQL query is understood as a sequence of logical transformations, even though its clauses are written in a different order. This model explains name visibility and result semantics; it does not prescribe the optimizer's physical execution plan.
  • FROM and joins establish the input row source before row filtering.
  • WHERE filters rows, while HAVING filters groups.
  • Window calculations observe the grouped, filtered row set without collapsing it.
  • SELECT computes the output expressions; DISTINCT then removes duplicate output rows.
  • ORDER BY establishes presentation order, and row limiting chooses a slice of that ordered result.
  • Logical order is not physical execution order.

Read a query in semantic order

Logical evaluation pipeline
A semantics and name-resolution model, not a claim that the engine materializes or physically executes every box in this order.
Clause order, visibility, and purpose
Logical stageWhat existsConsequence
FROM, ON, joinsInput rows and join matchesOuter joins may add null-extended rows
WHEREJoined rowsOnly predicate result TRUE survives
GROUP BY, aggregatesOne logical group per grouping keyDetail rows collapse into group results
HAVINGGroups and aggregate valuesWhole groups are retained or removed
WindowsRows after grouping and HAVINGAnalytics are added without further grouping
SELECTProjected expressions and aliasesAliases become available to later stages
DISTINCTProjected rowsDuplicate projected rows are eliminated
ORDER BYFinal result expressionsA deterministic sequence requires a total tie-breaker
LimitingOrdered resultA requested prefix or page is selected
Written order versus logical order
SELECT o.customer_id, SUM(i.quantity * i.unit_price) AS revenue
FROM orders AS o
JOIN order_items AS i ON i.order_id = o.order_id
WHERE o.status = 'PAID'
GROUP BY o.customer_id
HAVING SUM(i.quantity * i.unit_price) >= 1000
ORDER BY revenue DESC, o.customer_id;
The `revenue` alias is usable in `ORDER BY`, which is logically later than projection, but not generally in `WHERE`, which is earlier.

For the sample query, joins first form paid-order line rows, WHERE removes non-paid orders, grouping forms one group per customer, and HAVING keeps groups totaling at least 1000. Projection names the total revenue; ordering then sorts totals and uses customer_id to break ties.