If you really understand SQL execution order, half of SQL “confusion” disappears. Let’s go step by step in a clear + practical way.
🧠 SQL Execution Order (Logical Order)
Even though you write:
SELECT ...
FROM ...
WHERE ...
GROUP BY ...
HAVING ...
ORDER BY ...
👉 SQL actually executes like this:
🔥 1. FROM (including JOINs)
FROM employees e
JOIN departments d ON e.department_id = d.id
💡 What happens:
- Tables are loaded
- Joins are applied
- A working dataset (virtual table) is created
👉 This is the starting point
🔥 2. WHERE (Row Filtering)
💡 What happens:
- Filters rows before grouping
- Works on individual rows
❗ Cannot use:
- aggregates (
SUM, COUNT) - aliases from SELECT
🔥 3. GROUP BY
💡 What happens:
- Rows are grouped into buckets
- Each group becomes one unit
👉 After this:
- You can only access:
- grouped columns
- aggregated values
🔥 4. HAVING (Group Filtering)
HAVING SUM(salary) > 100000
💡 What happens:
- Filters groups, not rows
👉 Key difference:
- WHERE → row filter
- HAVING → group filter
🔥 5. SELECT (Final Projection)
SELECT department_id, SUM(salary)
💡 What happens:
- Columns are selected
- Expressions are evaluated
- Aliases are created
👉 Now aliases exist (important!)
🔥 6. DISTINCT (if used)
SELECT DISTINCT department_id
💡 What happens:
- Duplicate rows removed after SELECT
🔥 7. ORDER BY
ORDER BY total_salary DESC
💡 What happens:
- Final result is sorted
👉 Can use:
- aliases ✅
- column positions (
ORDER BY 2) ✅
🔥 8. LIMIT / OFFSET
💡 What happens:
- Final rows are trimmed
🎯 Full Flow (Easy Memory Trick)
👉 F-W-G-H-S-D-O-L
1 | FROM |
2 | WHERE |
3 | GROUP BY |
4 | HAVING |
5 | SELECT |
6 | DISTINCT |
7 | ORDER BY |
8 | LIMIT |
🔥 Example Walkthrough
SELECT department_id, SUM(salary) AS total
FROM employees
WHERE salary > 50000
GROUP BY department_id
HAVING SUM(salary) > 200000
ORDER BY total DESC
LIMIT 3;
🧩 Step-by-step:
- FROM → get employees
- WHERE → keep salary > 50K
- GROUP BY → group by department
- HAVING → keep groups where total > 200K
- SELECT → calculate SUM + alias
- ORDER BY → sort by total
- LIMIT → top 3 rows
⚠️ Common Mistakes Explained Using This
❌ Why this fails:
WHERE SUM(salary) > 100000
👉 Because WHERE runs before SUM exists
❌ Why alias fails in WHERE:
👉 Because SELECT hasn’t run yet
✅ But works in ORDER BY:
👉 Because SELECT already ran
🧠 Advanced (Important for interviews)
👉 Window Functions run AFTER GROUP BY but BEFORE ORDER BY
SELECT
department_id,
SUM(salary),
RANK() OVER (ORDER BY SUM(salary) DESC)
FROM employees
GROUP BY department_id;
Execution:
- GROUP BY → SUM
- THEN window function (
RANK)
🚀 Pro Tip (Real understanding)
Think of SQL as:
- Build data →
FROM - Filter rows →
WHERE - Group data →
GROUP BY - Filter groups →
HAVING - Shape output →
SELECT - Sort →
ORDER BY - Trim →
LIMIT
✅ Final takeaway
👉 SQL is not executed top-to-bottom as written
👉 It follows a logical pipeline
If you want next:
- 🔥 Visual diagram (step-by-step table transformation)
- 🧠 Trick questions based on execution order
- ⚡ Window function deep dive (very important for senior roles)
Just tell me 👍