Which students took every Math course? A join finds "at least one"; it cannot say "every". can.
r = π id, course_id (takes)
| id | course_id |
|---|---|
| S201 | MA-110 |
| S203 | MA-110 |
| S203 | MA-220 |
| S207 | MA-220 |
s = π course_id (σ dept_name = 'Math' (course))
| course_id |
|---|
| MA-110 |
| MA-220 |
r ÷ s
| id |
|---|
| S203 |
Definition
r(R) ÷ s(S), where every attribute of S is also in R:
- the schema of the result is
R − S(the attributes of r that are not in s), - a tuple t is in the result when, for every tuple u in s, the tuple (t, u) is in r.
If s is empty, every t in π R−S (r) passes, because there is no u to miss.
Division is a short form of the fundamental operators:
r ÷ s = π R−S (r) − π R−S ( (π R−S (r) × s) − r )Read the right side from the inside: π R−S (r) × s is every pair that "should" exist. Subtract r: the pairs that are missing. Their t values fail. Remove them from all t values.
In SQL
SQL has no ÷. Write "for every" as "no course is missing":
SELECT DISTINCT t.id
FROM takes AS t
WHERE NOT EXISTS (
SELECT course_id FROM course WHERE dept_name = 'Math'
EXCEPT
SELECT t2.course_id FROM takes AS t2 WHERE t2.id = t.id
);The inner query is "the Math courses that this student did not take". NOT EXISTS keeps the student when that is empty.