Nested Subqueries
A subquery is simply a select-from-where block placed inside another query. SQL lets you nest subqueries in the WHERE, FROM, and SELECT clauses.
select: Must return a single scalar value.from: Can return any valid relation (table).where: Used in expressions likeAttribute <operation> (subquery).
All examples on this page run on the course datasets: press Run on any query to see its result.
Subqueries in the WHERE Clause
Typically used to test set membership, set comparison, and set cardinality.
Set Membership: IN / NOT IN
Example: Find courses offered in Fall 2009 and in Spring 2008.
Swap
infornot into find courses offered in Fall 2009 but not in Spring 2008.
Set Comparison: SOME and ALL
| Clause | Meaning | Logic |
|---|---|---|
some |
True if comparison holds for at least one row in subquery | \(\exists\, t \in r : F \langle\text{comp}\rangle\, t\) |
all |
True if comparison holds for every row in subquery | \(\forall\, t \in r : F \langle\text{comp}\rangle\, t\) |
Example: Instructors earning more than some instructor in Biology:
Example: Instructors earning more than all instructors in Biology:
How the result is decided. Biology has two salaries: 45538.32 and 77036.18.
| Instructor | salary | > some | > all |
|---|---|---|---|
| Gutierrez | 45310.53 | ✗ | ✗ |
| Murata | 61387.56 | ✓ (beats 45538.32) | ✗ |
| Romero | 79070.08 | ✓ | ✓ (beats both) |
Test for Empty Sets: EXISTS
exists ris true ifris non-empty.not exists ris true ifris empty.
Example: Find courses offered in both Fall 2009 and Spring 2008, using a correlated subquery (inner query refers to the outer query’s variable).
Sis the correlation name (outer query variable)- The inner query referencing
Sis the correlated subquery
Example: Find teams that have played against all other teams (uses not exists + set difference logic):
For each team, “all other teams” minus “teams it has played” must be empty:
| Team | Other teams not yet played | Kept? |
|---|---|---|
| Amigos | none (empty) | ✓ |
| Thunder | Rainbow | ✗ |
| Rainbow | Thunder, All Stars, Arawali | ✗ |
Subqueries in the FROM Clause
A subquery can stand in for a table, letting you filter on an aggregate without HAVING.
Example: Average salary of departments where average salary exceeds 90,000:
The WITH Clause
with defines a temporary, named result (like a scratchpad table) visible only to the query that follows.
Example: Find the name of the department that has the maximum budget.
Multiple with blocks can be chained for multi-step logic:
Example: Find the names of the departments whose total salary expense is greater than the average total salary expense across all departments.
Subqueries in the SELECT Clause
A scalar subquery returns exactly one value, used wherever a single value is expected.
Modifying the Database
These statements change the dataset. Each example is wrapped in begin; … rollback; so the data is restored after you run it.
Deletion
begin;
-- Delete all instructors
delete from instructor;
-- Delete instructors from one department
delete from instructor where dept_name = 'Finance';
-- Delete instructors in departments located in a specific building
delete from instructor
where dept_name in (select dept_name
from department
where building = 'Taylor');
rollback;Tricky case: Delete instructors earning less than the average salary.
Insertion
begin;
insert into course
values ('CS-437', 'Database Systems', 'Comp. Sci.', 4);
-- with tot_cred set to null
insert into student
values ('3003', 'Green', 'Finance', null);
-- insert from another query's results
insert into student
select id, name, dept_name, 0
from instructor
where id not in (select id from student);
rollback;Updates
Conditional updates — give a 3% raise above 100,000, 5% below (order matters!):
Cleaner with a case statement (single pass, no ordering issues):
Updates with scalar subqueries — recompute total credits per student:
(Find the total credits earned by each student (excluding failed or uncollected grades) and update their record in the student table.)