What Really Happens Inside SQL? A Step‑by‑Step Walkthrough of Execution Order
This article breaks down the true execution sequence of an SQL query—from FROM and JOIN through WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, and finally LIMIT—explaining each stage with examples, code snippets, and visual diagrams to help developers write more efficient queries.
SQL Execution Order Overview
SQL does not evaluate a query strictly from left to right as it appears in the text. The database engine follows a fixed logical pipeline that determines how rows are produced, filtered, grouped, and finally returned.
Logical Processing Pipeline
FROM / JOIN – Resolve table references and apply join conditions to create an initial row set.
WHERE – Apply row‑level predicates that do not involve aggregates. Rows failing the condition are discarded before any grouping.
GROUP BY – Partition the remaining rows into groups based on the specified expressions. No rows are removed at this stage.
HAVING – Filter groups using predicates that may reference aggregate functions (e.g., AVG(), COUNT()). Only groups satisfying the condition survive.
SELECT – Project the required columns. If aggregate functions are present, the engine adds a new column for each computed value. Column names that appear in multiple tables must be qualified to avoid ambiguity.
DISTINCT – Remove duplicate rows from the result set, if requested.
ORDER BY – Sort the final rows according to the specified ordering expressions.
LIMIT – Truncate the sorted result set to the requested number of rows.
FROM, JOIN & WHERE
These clauses define which tables participate in the query and how they are linked.
FROM table1 JOIN table2 ON table1.id = table2.idA comma‑separated list with a WHERE condition is equivalent but can produce a Cartesian product if the join predicate is omitted.
FROM table1, table2 WHERE table1.id = table2.idGROUP BY
GROUP BYclusters rows according to the specified expression(s) without discarding any rows. For example, grouping by the parity of an id column creates two groups (odd and even) while preserving all rows.
HAVING vs. WHERE
WHERE can contain only non‑aggregate predicates. HAVING can reference aggregates, allowing conditions such as HAVING AVG(salary) < 5000.
WHERE before GROUP BY – Rows that do not satisfy the WHERE predicate are removed before grouping.
GROUP BY before HAVING – Rows are first grouped, then groups that fail the HAVING predicate are discarded. When the logical condition is equivalent, the final result is the same.
HAVING salary < AVG(salary)SELECT
After grouping, SELECT chooses which columns to return. Aggregate functions generate new columns (often shown in diagrams in a distinct colour). When multiple tables contain columns with the same name, qualify them (e.g., table1.id) to avoid ambiguity. Use DISTINCT if duplicate rows must be eliminated.
SELECT employee.id, DISTINCT name, salary, AVG(salary) FROM employee GROUP BY employee.id, nameORDER BY
The final step sorts the result set according to the specified columns. Sorting occurs after all other processing, and before any LIMIT is applied.
LIMIT
LIMITtruncates the sorted result set. Placing LIMIT before sorting would return an arbitrary subset, not the intended top‑N rows.
Example: to retrieve the three lowest salaries, first ORDER BY salary ASC and then LIMIT 3.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
