CMD Guide
HomeDatabasesSQL Fundamentals

What are SET operations

A set operation takes the output rows of two SELECT queries and combines them by treating each row as an element of a set, matching rows by comparing every selected column position-by-position (not by column name) and resolving duplicates according to the operator: UNION and friends are vertical row-stacking operations, in contrast to JOINs, which stitch tables horizontally column-by-column.

There are four logical set operators in standard SQL, organized as two pairs. Each pair has a default form that removes duplicates and an ALL form that keeps them:

OperatorMeaning (rows in result)Duplicate behavior
UNIONIn A or BRemoves duplicates (sorts/hashes to dedupe)
UNION ALLIn A or BKeeps every row (cheapest — just concatenates)
INTERSECTIn A and BRemoves duplicates
EXCEPT (Oracle: MINUS)In A but not in BRemoves duplicates

Worked example: two tables of city visitors

Suppose two analysts each pulled a list of customer cities. We want to reason about overlap. Take these two row-sets:

A (web signups)B (store walk-ins)
PunePune
DelhiPune
DelhiSurat

Notice A itself contains Delhi twice and B contains Pune twice — duplicates exist inside each input, which is exactly where the ALL distinction bites. Tracing each operator on these inputs:

  1. A UNION ALL B → just concatenates all 6 rows: {Pune, Delhi, Delhi, Pune, Pune, Surat}. No dedupe, no sort guaranteed.
  2. A UNION B → take the same 6 rows, then collapse to distinct values: {Pune, Delhi, Surat} (3 rows).
  3. A INTERSECT B → values present in both, deduped: Pune is in both; Delhi is only in A; Surat only in B → {Pune} (1 row).
  4. A EXCEPT B → distinct values of A with anything appearing in B removed: A has {Pune, Delhi}; drop Pune (it's in B) → {Delhi} (1 row).
diagram
diagram

The portability bug this page used to contain

The older version of this page listed all four operators as the "primary set operations in MySQL." That is wrong and would burn you in practice: MySQL had no native INTERSECT or EXCEPT until version 8.0.31 (released late 2022). On MySQL 5.7 and 8.0.0–8.0.30 — still common in production — only UNION and UNION ALL exist. Writing SELECT ... INTERSECT SELECT ... there is a syntax error.

Why the naive listing is wrong: it implies you can reach for any of the four on MySQL, but the next lessons themselves emulate INTERSECT/EXCEPT with joins and NOT IN precisely because the engine lacked them. The honest statement is: UNION/UNION ALL are universal; INTERSECT/EXCEPT are standard SQL, present in PostgreSQL, SQL Server, Oracle (as MINUS) and SQLite for years, but only in MySQL 8.0.31+.

Emulating INTERSECT / EXCEPT on old MySQL

-- INTERSECT (distinct rows in both)
SELECT DISTINCT a.city FROM A a
WHERE a.city IN (SELECT city FROM B);

-- EXCEPT (distinct rows in A but not B)
SELECT DISTINCT a.city FROM A a
WHERE a.city NOT IN (SELECT city FROM B WHERE city IS NOT NULL);

The WHERE city IS NOT NULL guard in the EXCEPT emulation is load-bearing: a single NULL inside a NOT IN subquery makes the whole predicate evaluate to UNKNOWN for every row, so the query silently returns zero rows. The real EXCEPT operator does not have this trap because it treats NULLs as equal to each other for matching.

Pitfalls

Takeaways


Sources: ISO/IEC 9075 SQL standard (set operators, duplicate semantics); PostgreSQL documentation, "Combining Queries (UNION, INTERSECT, EXCEPT)"; MySQL 8.0 Reference Manual, "Set Operations with UNION, INTERSECT, and EXCEPT" (INTERSECT/EXCEPT added in 8.0.31); Oracle Database SQL Language Reference (MINUS); Joe Celko, "SQL for Smarties," on NOT IN / NULL behavior. Re-authored and deepened for this guide: fixed the incorrect claim that MySQL natively supports INTERSECT/EXCEPT, added the mechanism, a positional-matching trace, and the NULL-in-NOT-IN pitfall.

🎯 STRICT STANDOUT: Why / worked / when-not / failure / drills — What are SET operations

Why this concept exists (judgment chain)

Set ops stack rows vertically and match by ordinal position/types, not names. UNION dedupes (sort/hash cost); UNION ALL concatenates. INTERSECT/EXCEPT are standard but only native in MySQL since 8.0.31 — portability is a production fact, not trivia. NULL equals NULL inside set ops.

Worked example with numbers or traced steps

A={Pune,Delhi,Delhi}; B={Pune,Pune,Surat}
UNION ALL → 6 rows; UNION → {Pune,Delhi,Surat}
INTERSECT → {Pune}; EXCEPT → {Delhi}
Positional bug: SELECT city,country UNION SELECT country,city silently mismatches.
MySQL <8.0.31: INTERSECT/EXCEPT syntax error — emulate with IN / NOT IN + IS NOT NULL guard.
Set-op NULL matching collapses two all-NULL rows under UNION.

When NOT to use / named alternative

Prefer JOIN when you need horizontal attributes from both sides. Prefer UNION ALL when inputs are disjoint or duplicates are wanted — skip dedupe cost. Emulate EXCEPT with NOT EXISTS rather than NOT IN when nullable. Avoid set ops for wide rows when you only need key membership.

Failure / ops fingerprint

Cross-engine deploy fails on INTERSECT. Silent garbage from column order swap. UNION spiking CPU/temp on huge bags. NOT IN emulation returns empty after a NULL sneaks into B. Ops: CI matrix tests MySQL version gates; EXPLAIN for HashAggregate/Unique on UNION.

Hostile-panel Q&As (model answers)

Q1. UNION vs UNION ALL performance?
Model answer: UNION must dedupe (sort/hash); UNION ALL is pure append — default when safe.

Q2. MySQL INTERSECT availability?
Model answer: Native only from 8.0.31; older versions need IN/EXISTS rewrites.

Q3. Why guard NOT IN with IS NOT NULL?
Model answer: A single NULL in the subquery makes x NOT IN (...) UNKNOWN for all x → empty result.

🤖 Don't fully get this? Learn it with Claude

Stuck on What are SET operations? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **What are SET operations** (Databases) and want to truly understand it. Explain What are SET operations from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **What are SET operations** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **What are SET operations** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **What are SET operations** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes