Bird
Raised Fist0
SQLquery~10 mins

Correlated subquery execution model in SQL - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Correlated subquery execution model
Start Outer Query Row
Evaluate Correlated Subquery
Use Outer Row Value in Subquery
Subquery Returns Result
Combine Subquery Result with Outer Row
Move to Next Outer Query Row
Repeat
End when no more outer rows
For each row in the outer query, the correlated subquery runs using values from that row, then returns a result combined with the outer row.
Execution Sample
SQL
SELECT e.name, e.salary
FROM employees e
WHERE e.salary > (
  SELECT AVG(salary)
  FROM employees
  WHERE department = e.department
);
Find employees whose salary is above the average salary of their own department.
Execution Table
StepOuter Row (e.name, e.department, e.salary)Subquery ConditionSubquery Result (AVG salary)Outer Condition (e.salary > AVG)Action
1(Alice, Sales, 5000)department = 'Sales'45005000 > 4500 = TrueInclude Alice
2(Bob, Sales, 4000)department = 'Sales'45004000 > 4500 = FalseExclude Bob
3(Carol, HR, 6000)department = 'HR'55006000 > 5500 = TrueInclude Carol
4(Dave, HR, 5000)department = 'HR'55005000 > 5500 = FalseExclude Dave
5(Eve, IT, 7000)department = 'IT'70007000 > 7000 = FalseExclude Eve
6No more rows---Stop execution
💡 No more outer rows to process, query ends.
Variable Tracker
VariableStartAfter 1After 2After 3After 4After 5Final
e.nameN/AAliceBobCarolDaveEveN/A
e.departmentN/ASalesSalesHRHRITN/A
e.salaryN/A50004000600050007000N/A
Subquery AVGN/A45004500550055007000N/A
Outer Condition ResultN/ATrueFalseTrueFalseFalseN/A
Key Moments - 3 Insights
Why does the subquery run multiple times instead of just once?
Because the subquery depends on the current outer row's department value, it must run for each outer row to get the correct average for that department (see execution_table rows 1-5).
What happens if the subquery returns no rows for a department?
The AVG function returns NULL, so the outer condition comparing salary > NULL becomes false, excluding that outer row (not shown in this example but important to know).
Why is Eve excluded even though her salary equals the average?
The condition uses > (greater than), so equality does not satisfy it. Eve's salary equals the average, so the condition is false (see execution_table row 5).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the subquery AVG salary result when processing Carol's row?
A4500
B6000
C5500
D7000
💡 Hint
Check execution_table row 3 under 'Subquery Result (AVG salary)'.
At which step does the outer condition become false for the first time?
AStep 2
BStep 3
CStep 1
DStep 5
💡 Hint
Look at 'Outer Condition Result' column in variable_tracker after each step.
If the condition changed to >= instead of >, which employee would be included additionally?
ADave
BEve
CBob
DNo change
💡 Hint
Check execution_table row 5 where Eve's salary equals the average but was excluded due to > condition.
Concept Snapshot
Correlated Subquery:
- Runs once per outer query row
- Uses outer row values inside subquery
- Returns result combined with outer row
- Useful for row-by-row comparisons
- Can be slower due to repeated subquery execution
Full Transcript
A correlated subquery runs once for each row of the outer query. It uses values from the current outer row inside the subquery condition. For example, to find employees earning more than their department's average salary, the subquery calculates the average salary for the department of the current employee. This means the subquery runs multiple times, once per employee. The outer query then compares the employee's salary to this average. If the condition is true, the employee is included in the result. This process repeats until all outer rows are processed. Understanding this step-by-step helps beginners see why correlated subqueries can be slower but are powerful for row-specific filtering.

Practice

(1/5)
1. What is a correlated subquery in SQL?
easy
A. A subquery that runs independently of the outer query
B. A subquery that uses values from the outer query to filter results
C. A query that joins two tables without conditions
D. A query that only returns aggregate values

Solution

  1. Step 1: Understand subquery types

    A correlated subquery depends on the outer query's current row to run.
  2. Step 2: Identify correlation

    It uses columns from the outer query inside the subquery's WHERE clause.
  3. Final Answer:

    A subquery that uses values from the outer query to filter results -> Option B
  4. Quick Check:

    Correlated subquery = uses outer query values [OK]
Hint: Correlated subqueries reference outer query columns [OK]
Common Mistakes:
  • Thinking subquery runs once independently
  • Confusing with JOIN operations
  • Assuming it returns only aggregates
2. Which of the following is the correct syntax for a correlated subquery?
easy
A. SELECT e.name FROM employees e WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department = e.department)
B. SELECT e.name FROM employees e WHERE salary > 50000
C. SELECT e.name FROM employees e WHERE e.salary > (SELECT AVG(salary) FROM employees)
D. SELECT e.name FROM employees e JOIN departments d ON e.department = d.id

Solution

  1. Step 1: Identify correlation in subquery

    SELECT e.name FROM employees e WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department = e.department) uses 'e.department' inside the subquery, linking it to the outer query.
  2. Step 2: Check other options

    SELECT e.name FROM employees e WHERE e.salary > (SELECT AVG(salary) FROM employees) has no reference to outer query in subquery; the option with 'salary > 50000' lacks a subquery and the JOIN option is not a subquery.
  3. Final Answer:

    SELECT e.name FROM employees e WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department = e.department) -> Option A
  4. Quick Check:

    Correlation needs outer query column inside subquery [OK]
Hint: Look for outer query columns inside subquery WHERE clause [OK]
Common Mistakes:
  • Missing outer query reference inside subquery
  • Confusing JOIN with subquery
  • Using subquery without correlation
3. Given the tables employees(id, name, department, salary) and the query:
SELECT e1.name FROM employees e1 WHERE e1.salary > (SELECT AVG(e2.salary) FROM employees e2 WHERE e2.department = e1.department);

What does this query return?
medium
A. Employees whose salary is above the average salary of their own department
B. Employees whose salary is above the average salary of all employees
C. Employees with salary above 50000
D. All employees regardless of salary

Solution

  1. Step 1: Understand the subquery correlation

    The subquery calculates average salary for the department of the current employee (e1.department).
  2. Step 2: Compare salaries

    The outer query selects employees whose salary is greater than that department average.
  3. Final Answer:

    Employees whose salary is above the average salary of their own department -> Option A
  4. Quick Check:

    Salary > department average = Employees whose salary is above the average salary of their own department [OK]
Hint: Check which outer column is used inside subquery condition [OK]
Common Mistakes:
  • Assuming average is for all employees
  • Ignoring the correlation condition
  • Confusing with simple WHERE salary > value
4. Identify the error in the following correlated subquery:
SELECT c.customer_id FROM customers c WHERE c.orders_count > (SELECT AVG(o.orders_count) FROM orders o WHERE o.customer_id = c.customer_id);
medium
A. The subquery will return multiple rows causing an error
B. The subquery uses a wrong table alias 'o' which is not defined
C. The subquery compares orders_count incorrectly; should use SUM instead of AVG
D. The subquery references the outer query correctly; no error

Solution

  1. Step 1: Analyze correlation

    The subquery correctly uses 'c.customer_id' from the outer query in its WHERE clause.
  2. Step 2: Check aggregation and output

    AVG(o.orders_count) is an aggregate that returns a single scalar value, even for customers with multiple orders.
  3. Final Answer:

    The subquery references the outer query correctly; no error -> Option D
  4. Quick Check:

    Subquery must return single value for comparison [OK]
Hint: Ensure subquery returns one value for comparison [OK]
Common Mistakes:
  • Thinking AVG returns multiple rows without GROUP BY
  • Assuming alias 'o' is undefined
  • Believing SUM is needed instead of AVG
5. You want to find all products whose price is higher than the average price of products in the same category. Which query correctly uses a correlated subquery to achieve this?
hard
A. SELECT p.product_name FROM products p JOIN categories c ON p.category = c.id WHERE p.price > c.avg_price
B. SELECT p.product_name FROM products p WHERE p.price > (SELECT AVG(price) FROM products)
C. SELECT p.product_name FROM products p WHERE p.price > (SELECT AVG(price) FROM products WHERE category = p.category)
D. SELECT product_name FROM products WHERE price > ALL (SELECT price FROM products)

Solution

  1. Step 1: Identify correlation condition

    SELECT p.product_name FROM products p WHERE p.price > (SELECT AVG(price) FROM products WHERE category = p.category) uses 'p.category' inside the subquery to calculate average price per category, correlating outer and inner queries.
  2. Step 2: Verify other options

    SELECT p.product_name FROM products p WHERE p.price > (SELECT AVG(price) FROM products) compares to overall average, not per category; the option using JOIN with categories uses a JOIN but no subquery; the option using > ALL compares to all individual prices, not average.
  3. Final Answer:

    SELECT p.product_name FROM products p WHERE p.price > (SELECT AVG(price) FROM products WHERE category = p.category) -> Option C
  4. Quick Check:

    Correlated subquery filters by category [OK]
Hint: Use outer query column inside subquery WHERE for correlation [OK]
Common Mistakes:
  • Using overall average instead of per category
  • Confusing JOIN with subquery
  • Using ALL instead of AVG in subquery