Memra

Set Operations: UNION, INTERSECT & EXCEPT (MINUS)

Combine whole result sets with set algebra — UNION (either, deduped), INTERSECT (both), EXCEPT/MINUS (in the first but not the second) — under the union-compatibility rule.

Algebra over result sets

The operators in this lesson combine two *result sets* (not two tables) into one. They answer "in both", "in either", or "in one but not the other":

- UNION — rows in *either* query; duplicates removed (like DISTINCT). UNION ALL keeps duplicates and is faster. - INTERSECT — rows in *both* queries. - EXCEPT — rows in the first query but not the second. (The Oracle/textbook name is MINUS; Postgres uses EXCEPT — same operation.)

Union compatibility

For any of the three, the two SELECTs must be union-compatible: the same number of columns, in the same order, with compatible data types in each position. The column *names* don't have to match — the result takes its names from the first query. A single trailing ORDER BY applies to the combined result and goes only after the last SELECT.

Worked example: students in both COMP 268 and COMP 378 (INTERSECT)

*Question:* which students have registered in both COMP 268 and COMP 378? Build each enrolled-student set, then intersect:

SELECT r.student_id
FROM   registrations r
JOIN   sections s ON s.section_id = r.section_id
JOIN   courses  c ON c.course_id = s.course_id
WHERE  c.code = 'COMP 268'
INTERSECT
SELECT r.student_id
FROM   registrations r
JOIN   sections s ON s.section_id = r.section_id
JOIN   courses  c ON c.course_id = s.course_id
WHERE  c.code = 'COMP 378';

The first SELECT lists every student enrolled in a COMP 268 section; the second lists every student enrolled in a COMP 378 section; INTERSECT keeps the ids appearing in both. Result: students 1, 4, 9. Both sides project a single student_id column, so they are union-compatible.

Worked example: offered in I-2018 but not II-2018 (EXCEPT)

*Question:* which courses ran in semester I-2018 but not in II-2018?

SELECT course_id FROM sections WHERE semester = 'I-2018'
EXCEPT
SELECT course_id FROM sections WHERE semester = 'II-2018';

EXCEPT keeps course ids in the first set that are absent from the second — courses offered in I-2018 only. Result: courses 1 and 5. Swap the two SELECTs and you get the opposite difference (offered in II-2018 but not I-2018) — order matters for EXCEPT, unlike UNION/INTERSECT.

NORMAL ~/memra/learn/comp-378/set-operations-union-intersect-except utf-8 LF