Subqueries

Advanced

⏱️ 17 mins read

What You'll Learn

A subquery is a query nested inside another. Non-correlated subqueries run once independently. Correlated subqueries reference the outer query and run once per outer row — they can be slow on large tables. Subqueries can appear in SELECT, FROM, WHERE, and HAVING clauses.

Syntax

-- WHERE subquery
SELECT * FROM table
WHERE col > (SELECT AVG(col) FROM table);

-- FROM subquery (derived table)
SELECT * FROM (SELECT ...) AS alias;

Example

-- Non-correlated: runs once
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

-- Subquery in FROM
SELECT dept, avg_sal
FROM (
  SELECT department AS dept,
         AVG(salary) AS avg_sal
  FROM employees GROUP BY department
) dept_stats
WHERE avg_sal > 75000;

-- Correlated: runs per outer row (SLOW)
SELECT e.name, e.salary
FROM employees e
WHERE e.salary = (
  SELECT MAX(salary) FROM employees
  WHERE department = e.department -- references outer e
);

Common Mistakes

Correlated subqueries run N times (once per row in the outer query). On a 1M-row table, that's 1M subquery executions. Prefer JOINs or CTEs for performance. Also: NOT IN with a subquery that returns NULLs always produces empty results — use NOT EXISTS instead.

Interview Tips

Know when to use EXISTS vs IN. EXISTS stops at the first match (faster for large sets). Correlated subqueries are often rewritable as JOINs — show both approaches and discuss trade-offs.

Practice

Find the top earner in each department using a correlated subquery. Then rewrite the same query using a CTE with ROW_NUMBER().