SET Operators: Real Use Cases
Combine similar tables with UNION ALL, detect changes (delta) with EXCEPT, and check data completeness between source and warehouse.
SET operators aren't just exam topics — data engineers use them daily. Here are the three classic use cases from the course, on IPL data, plus the JOINs & SET cheat sheet.
Use case 1 — Combine information (similar tables)
Combining similar tables means stacking tables that have the same structure but hold different slices of data (one per season, per region, per year) into one table for reporting, using UNION ALL.
Each season's runs are kept in a separate table, runs_2023 and runs_2024 (the playground setup creates them):
sql
SELECT 'IPL 2023' AS season, name, runs FROM runs_2023
UNION ALL
SELECT 'IPL 2024' AS season, name, runs FROM runs_2024;| season | name | runs |
|---|---|---|
| IPL 2023 | Virat Kohli | 639 |
| IPL 2023 | Rohit Sharma | 332 |
| IPL 2023 | MS Dhoni | 104 |
| IPL 2024 | Virat Kohli | 741 |
| IPL 2024 | Rohit Sharma | 417 |
| IPL 2024 | MS Dhoni | 161 |
Why UNION ALL (not UNION)? The season column makes every row unique anyway, so de-duplication would be wasted work — and without it, UNION could wrongly merge two seasons where a player scored the same runs.
Once stacked, you can analyse across seasons:
sql
SELECT name, SUM(runs) AS total_runs
FROM (
SELECT name, runs FROM runs_2023
UNION ALL
SELECT name, runs FROM runs_2024
) AS seasons
GROUP BY name
ORDER BY total_runs DESC;| name | total_runs |
|---|---|
| Virat Kohli | 1380 |
| Rohit Sharma | 749 |
| MS Dhoni | 265 |
Use case 2 — Delta detection
Delta detection means finding what changed between two versions of the same dataset (old vs new) — rows that were removed and rows that were added — using EXCEPT in both directions.
squad_old: Virat Kohli, Rohit Sharma, MS Dhoni, David Warner
squad_new: Virat Kohli, Rohit Sharma, MS Dhoni, Jos Buttler
sql
-- who left? (in old, not in new)
SELECT name FROM squad_old
EXCEPT
SELECT name FROM squad_new;| name |
|---|
| David Warner |
sql
-- who joined? (in new, not in old)
SELECT name FROM squad_new
EXCEPT
SELECT name FROM squad_old;| name |
|---|
| Jos Buttler |
And INTERSECT gives who stayed: Kohli, Rohit, Dhoni. In data pipelines, the same idea finds new or changed rows in today's file compared with yesterday's, so only the delta is loaded.
Use case 3 — Completeness check
A completeness check verifies that no data was lost when moving data from a source system to a target (e.g. a data warehouse):
source EXCEPT targetmust return no rows.
score_source has matches 101, 102, 103, 104. The warehouse table score_dw is missing one (match 103):
sql
SELECT * FROM score_source
EXCEPT
SELECT * FROM score_dw;| match_id | runs |
|---|---|
| 103 | 201 |
| Result | Meaning |
|---|---|
| empty result | the warehouse is complete ✅ |
| rows returned | those rows are missing (or different) in the warehouse ❌ |
Run it both ways: score_dw EXCEPT score_source finds rows in the warehouse that don't exist in the source (wrong or extra data). Because EXCEPT compares whole rows, it also catches a row whose values changed (e.g. runs 201 vs 210), not just missing ones.
Bonus — JOINs and SET cheat sheet
| Tool | What it returns |
|---|---|
| INNER JOIN | only matching rows |
| LEFT JOIN | all of A + matches from B |
| RIGHT JOIN | all of B + matches from A |
| FULL JOIN | everything from both |
| LEFT JOIN … WHERE B.key IS NULL | A rows with no match (anti join) |
| CROSS JOIN | every combination of A and B |
| UNION / UNION ALL | stack rows (distinct / with duplicates) |
| EXCEPT / INTERSECT | difference / common rows |
Common mistakes
- ❌ Using UNION to combine seasons and losing rows that happen to be identical. ✅ UNION ALL + a label column.
- ❌ Running the completeness check in one direction only. ✅ Check source→target and target→source.
- ❌
SELECT *EXCEPTSELECT *on tables whose columns are in a different order. ✅ List the columns explicitly in the same order.
Interview tip
Q: How would you verify that a data migration copied every row correctly?
A: Compare counts first, then run SELECT cols FROM source EXCEPT SELECT cols FROM target (and the reverse). Both must return zero rows.
Key points to remember
- Combine similar tables (e.g. one per season) with UNION ALL plus a label column like 'IPL 2023' AS season.
- Delta detection: old EXCEPT new = removed rows; new EXCEPT old = added rows; INTERSECT = unchanged.
- Completeness check: source EXCEPT target must be empty — any rows returned are missing or different in the target.
- Run completeness checks in both directions to also catch extra or wrong rows in the target.
- EXCEPT compares whole rows, so it catches changed values, not just missing keys.
- Stacked data can be wrapped in a subquery and aggregated (SUM, COUNT) across all sources.
Try it yourself
Use case 1: combine seasons with UNION ALL
This example runs a small setup step first — click to see it
CREATE TABLE runs_2023 (name VARCHAR(50), runs INT);
INSERT INTO runs_2023 (name, runs) VALUES ('Virat Kohli', 639), ('Rohit Sharma', 332), ('MS Dhoni', 104);
CREATE TABLE runs_2024 (name VARCHAR(50), runs INT);
INSERT INTO runs_2024 (name, runs) VALUES ('Virat Kohli', 741), ('Rohit Sharma', 417), ('MS Dhoni', 161);Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Use case 2: delta detection between squads
This example runs a small setup step first — click to see it
CREATE TABLE squad_old (name VARCHAR(50));
INSERT INTO squad_old (name) VALUES ('Virat Kohli'), ('Rohit Sharma'), ('MS Dhoni'), ('David Warner');
CREATE TABLE squad_new (name VARCHAR(50));
INSERT INTO squad_new (name) VALUES ('Virat Kohli'), ('Rohit Sharma'), ('MS Dhoni'), ('Jos Buttler');Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Use case 3: completeness check source vs warehouse
This example runs a small setup step first — click to see it
CREATE TABLE score_source (match_id INT, runs INT); INSERT INTO score_source (match_id, runs) VALUES (101, 182), (102, 165), (103, 201), (104, 148); CREATE TABLE score_dw (match_id INT, runs INT); INSERT INTO score_dw (match_id, runs) VALUES (101, 182), (102, 165), (104, 148);
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Practice: fix the warehouse and re-check
This example runs a small setup step first — click to see it
CREATE TABLE score_source (match_id INT, runs INT); INSERT INTO score_source (match_id, runs) VALUES (101, 182), (102, 165), (103, 201), (104, 148); CREATE TABLE score_dw (match_id INT, runs INT); INSERT INTO score_dw (match_id, runs) VALUES (101, 182), (102, 165), (104, 148);
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Revision Flashcards
Tap a card to flip it and see the answer.
