Scalar subquery
WHERE salary > (
SELECT AVG(salary)
FROM employees
)Valid where one expression is expected. More than one returned row causes an error.
CodeBhavyaCompose queries in layers, test existence safely and calculate ranks, comparisons and running results while keeping each source row visible.
Before choosing syntax, ask how many rows and columns the inner query is allowed to return.
WHERE salary > (
SELECT AVG(salary)
FROM employees
)Valid where one expression is expected. More than one returned row causes an error.
WHERE dept_id IN (
SELECT dept_id
FROM active_departments
)Feeds a membership or quantified comparison such as IN, ANY or ALL.
FROM (
SELECT dept_id, AVG(salary) avg_sal
FROM employees GROUP BY dept_id
) AS statsBehaves like a temporary row source inside this statement and needs an alias.
WHERE salary > (
SELECT AVG(e2.salary)
FROM employees e2
WHERE e2.dept_id = e.dept_id
)References the current outer row. Think row-by-row even if the optimizer rewrites it.
Is this value equal to a member of the returned list?
dept_id IN (SELECT dept_id ...)Does the correlated inner query return at least one row?
EXISTS (SELECT 1 FROM ...)Is the value greater than at least one value in the set?
salary > ANY (SELECT salary ...)Is the value greater than every value in the set?
salary > ALL (SELECT salary ...)If the subquery set contains NULL, x NOT IN (...) can become UNKNOWN for every candidate and return no rows. For anti-matching, a correlated NOT EXISTS is usually clearer and NULL-safe.
WHERE NOT EXISTS (
SELECT 1 FROM registrations r
WHERE r.student_id = s.student_id
)Alias e supplies e.dept_id.
Runs conceptually with the supplied department.
The outer row remains in the result.
For each outer row, evaluate the inner query using that row’s correlated value, then test the predicate.
The database optimizer may decorrelate the query into joins or other operations. SQL states the result, not a guaranteed loop.
Check indexes on correlated lookup columns and compare an equivalent join or pre-aggregation when data is large.
WITH department_stats AS (
SELECT dept_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY dept_id
), above_average AS (
SELECT e.*
FROM employees e
JOIN department_stats d USING (dept_id)
WHERE e.salary > d.avg_salary
)
SELECT * FROM above_average;Name intermediate results by meaning, not by implementation details.
A CTE exists only for the statement that follows it.
A CTE is not automatically a stored table or guaranteed optimization barrier; behavior varies by database and version.
SELECT employee_id, manager_id, 0 depthCreates the initial working rows.
JOIN hierarchy h ON e.manager_id = h.employee_idFinds the next layer from the previous result.
No new rowsTermination occurs when the recursive member produces nothing new, or an explicit depth guard stops it.
SELECT name, branch, score,
DENSE_RANK() OVER (
PARTITION BY branch
ORDER BY score DESC
) AS branch_rank
FROM students;DENSE_RANK() defines the calculation.
Restarts the calculation for each branch; omit it for one global window.
Defines row sequence inside each partition.
For running aggregates, the frame identifies which neighboring rows participate.
Unique sequence even when scores tie.
Ties share rank and leave a gap.
Ties share rank without a gap.
Reads a neighboring row without a self join.
Aggregates over a window while preserving every detail row.
One result row per group, unless further joins restore detail.
Each input row remains, with a calculation added beside it.
| Question | Best starting tool | Why |
|---|---|---|
| Compare every salary with one overall average | Scalar subquery | Inner query returns one value. |
| Keep students who have at least one registration | EXISTS | The existence of a match matters, not its columns. |
| Find employees above their own department average | Correlated subquery or grouped CTE + join | The comparison value varies by department. |
| Make a long transformation readable | CTE | Each stage receives a meaningful name. |
| Walk an organization hierarchy | Recursive CTE | Each iteration discovers the next level. |
| Rank students without hiding individual rows | Window function | The result keeps one row per student. |
Choose a scenario, then move through outer rows to see the inner result, truth value and final decision.
Change the function and partition. The same detail rows remain while calculated values change.
Mark this level when you can choose and explain the simplest correct advanced-SQL tool.
Saved in this browser only.