Memra

Set Operations: UNION, INTERSECT & EXCEPT (MINUS)

◈ 5 cards

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