Topics
The correlated subqueries can be applied in several ways within SQL queries, enabling the inner query to reference and depend on values from the outer query. This dependency means the inner query is typically executed once for each row processed by the outer query.
1. Inside select
Used in the SELECT list to calculate or retrieve a value for each row returned by the outer query, often summarizing related data:
Example: Finding Average Departmental Salary for Each Employee
SELECT lastname, firstname, salary, (
SELECT avg(salary) FROM employee e2
WHERE e2.dep_id = e1.dep_id
) AS avg_dept_salary
FROM employee e1
2. Inside where
Used in the WHERE clause to filter rows from the outer query based on a condition that involves the results of the subquery, where the subquery’s filtering depends on outer query:
Example: Employees Earning More Than Their Department’s Average Salary
SELECT lastname, firstname, salary
FROM employee e1
WHERE e1.salary > (
SELECT avg(salary)
FROM employee e2
WHERE e2.dept_id = e1.dept_id
)
Example: Employees Who Never Received An Award
SELECT lastname, firstname
FROM employees e1
WHERE NOT EXISTS (
SELECT ph.lastname FROM payment_history ph
WHERE ph.emp_id = e1.employee_id
AND ph.payment_type =’award’
)
3. Inside having
When used with GROUP BY, only fields present in the GROUP BY clause or aggregate functions can be used in the inner query’s comparison within the HAVING clause:
Example: Filtering Groups by Average Vacation Hours Relative to Marital Status Average In other words, we want to answer a question similar to “do married accountants have, on average, more remaining vacation, than married employees in general?“
SELECT JobTitle, MaritalStatus, AVG(VacationHours)
FROM HumanResources.Employee AS E
GROUP BY JobTitle, MaritalStatus
HAVING AVG(VacationHours) > (
SELECT AVG(VacationHours)
FROM HumanResources.Employee AS Emp
WHERE Emp.MaritalStatus = E.MaritalStatus
)
4. Inside update
or delete
Example: Updating Employee’s Total Money Earned Use a correlated subquery to calculate the sum of payments for each employee from the payment_history
table and update the all_money_made
column in the employee table.
UPDATE employee emp
SET all_money_made = (
SELECT SUM(payment)
FROM payment_history
WHERE employee_id = emp.emp_id
)