Databases 6 min read

Understanding the Real Execution Order of SQL Queries

This article explains the true execution sequence of SQL statements—starting with FROM and JOIN, then WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, and LIMIT—illustrating each step with diagrams, examples, and code snippets to clarify how databases process queries.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Understanding the Real Execution Order of SQL Queries

SQL Execution Order

Relational databases evaluate a SELECT statement in a logical sequence that differs from the textual order of the clauses.

FROM / JOIN – Resolve table references and join conditions, producing an initial row set.

WHERE – Apply row‑level predicates that do not involve aggregates.

GROUP BY – Partition the filtered rows into groups based on the listed columns.

HAVING – Filter groups; predicates may reference aggregate functions.

SELECT – Compute the final column list, evaluate aggregate expressions, and resolve column references. Duplicate column names must be qualified with their source table.

DISTINCT – Remove duplicate rows from the result set.

ORDER BY – Sort the rows according to the specified ordering expressions.

LIMIT – Return only the requested number of rows after sorting.

FROM and JOIN

These clauses define which tables participate in the query and how they are related.

FROM table1 JOIN table2 ON table1.id = table2.id

If multiple tables are listed without explicit JOIN, the join condition must appear in the WHERE clause; otherwise a Cartesian product is produced.

FROM table1, table2 WHERE table1.id = table2.id

WHERE

The WHERE clause filters rows before any grouping occurs. Only non‑aggregate predicates are allowed.

GROUP BY

GROUP BY

partitions the intermediate result set into groups based on the specified columns. It does not filter rows.

SELECT id % 2 AS parity, COUNT(*) FROM employees GROUP BY parity;

HAVING vs. WHERE

HAVING

can contain both ordinary predicates and aggregate functions, allowing post‑group filtering. In many cases a HAVING clause can replace a WHERE clause, but WHERE is evaluated earlier.

-- Filter rows before grouping
SELECT * FROM sales WHERE amount > 1000;

-- Filter groups after grouping
SELECT region, SUM(amount) AS total FROM sales GROUP BY region HAVING total > 5000;

SELECT

After grouping, SELECT extracts the desired columns and computes aggregates. Aggregate functions add new columns to the result set.

SELECT employee.id, name, salary, AVG(salary) AS avg_salary FROM employee GROUP BY employee.id, name, salary;

DISTINCT

If duplicate rows remain after SELECT, DISTINCT removes them.

SELECT DISTINCT department FROM employee;

ORDER BY

The final step orders the result set according to one or more expressions.

SELECT id, name FROM employee ORDER BY id ASC;

LIMIT

LIMIT

is applied after ORDER BY. Placing LIMIT before sorting can produce incorrect results because the database would truncate before ordering.

-- Retrieve the three lowest salaries
SELECT * FROM employee ORDER BY salary ASC LIMIT 3;
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

SQLdatabaseJOINQuery ExecutionOrder ByFROMGROUP BYHAVING
Liangxu Linux
Written by

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.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.