Phase 4 · Subqueries, CTEs and set operations · Topic 4.5

UNION, UNION ALL, INTERSECT and EXCEPT

Should know

Set operators stack the results of two queries: UNION ALL keeps every row, UNION removes duplicates, INTERSECT keeps rows found in both, and EXCEPT keeps rows in the first but not the second.

Not started

Step 1 Understand it

Why you need it. Sometimes the you need come from two places: every city mentioned by departments or customers; cities that have both a department and a customer. put side by side; put results on top of each other.

Watch it happen

AnimationSet operators combine two results: stack, dedupe, both, or only the first
Read the animation as text
  1. Two queries that each return one column of cities. A set operator puts their results together — they need the same number of columns, of matching types.
  2. UNION ALL simply stacks the two results, duplicates and all. It is the fast one: no checking.
  3. UNION stacks them, then removes duplicate rows: 5 different cities are left. Removing duplicates costs a sort or a hash.
  4. INTERSECT keeps the rows found in both results: Leeds and London.
  5. EXCEPT keeps rows of the first result that are not in the second: Manchester has a department but no customer.

Picture it

flowchart LR
  A["query 1 rows"] --> U["UNION ALL: all rows"]
  B["query 2 rows"] --> U
  A --> UD["UNION: all rows, duplicates removed"]
  B --> UD
  A --> I["INTERSECT: rows in both"]
  B --> I
  A --> E["EXCEPT: rows in query 1 only"]
Set operators combine two results vertically. Both must return the same number of , with matching types; the names come from the first query.

The idea

Write two SELECTs with the same number of columns, of matching types, and put a set operator between them. The column names come from the first . simply stacks the rows — fast, and keeps duplicates. UNION stacks them and removes duplicate rows — which costs a sort or hash. keeps rows in both results; EXCEPT keeps rows of the first that are not in the second. A single at the very end sorts the combined result.

The shape of it

sql
SELECT col_a, col_b FROM table_one
UNION ALL
SELECT col_x, col_y FROM table_two
ORDER BY col_a;

Words in lower case are the parts you fill in.

How it works, step by step

  1. Both SELECTs return one column: department locations and customer cities.
  2. UNION stacks them (10 rows) and removes duplicate rows, leaving 5 different cities, including .
  3. UNION ALL keeps all of them; a source column shows where each row came from.
  4. INTERSECT keeps only cities in both lists: Leeds and London.
  5. EXCEPT keeps department cities with no customer: Manchester.

Analogy

Two class lists. UNION ALL staples them together. UNION staples them and crosses out anyone listed twice. INTERSECT is pupils on both lists. EXCEPT is pupils on the first list but not on the second.

Where the analogy breaks

Pupils are matched by name. Set operators match whole rows, column by column — so adding a column that differs (like a source label) stops rows from counting as duplicates.

Worked examples

UNION: every city, once

sql
SELECT location AS city FROM departments
UNION
SELECT city FROM customers
ORDER BY city;

5 rows

city
NULL
Bristol
Leeds
London
Manchester

Duplicates are removed, and the NULLs collapse into one row too.

UNION ALL: keep everything, with a label

sql
SELECT 'department' AS source, location AS city FROM departments
UNION ALL
SELECT 'customer', city FROM customers WHERE city IS NOT NULL
ORDER BY city, source;

9 rows

sourcecity
customerBristol
customerLeeds
customerLeeds
departmentLeeds
customerLondon
customerLondon
departmentLondon
departmentLondon
departmentManchester

INTERSECT: in both

sql
SELECT city FROM customers
INTERSECT
SELECT location FROM departments
ORDER BY city;

2 rows

city
Leeds
London

EXCEPT: in the first, not the second

sql
SELECT location FROM departments
EXCEPT
SELECT city FROM customers
ORDER BY location;

1 row

location
Manchester

Must-know points

  • Both queries need the same number of columns, in the same order, with compatible types.
  • UNION ALL keeps duplicates and is faster; UNION removes them.
  • Use UNION ALL unless you really need duplicates removed.
  • INTERSECT and EXCEPT also remove duplicates from their result.
  • One ORDER BY, at the end, sorts the combined result; column names come from the first query.

Common mistakes

  • Using UNION when the two sets can't overlap — paying for duplicate removal you don't need.
  • Putting ORDER BY on the first query instead of at the end.
  • Lining columns up in a different order in the second query: they are matched by position, not by name.

In other databases

  • Oracle calls EXCEPT MINUS. only added INTERSECT and EXCEPT in version 8.0.31.

Step 2 Go further (free, optional)

Optional. The notes above are written to be enough on their own. These free resources give a second explanation and more practice.

Step 3 Practise

Try each one yourself first: out loud, or written and run in the practice box below, which saves every query you run. Then open the answer and compare.

  1. ExplainSay what it does and when to use it, in plain words, with no notes.

    Explain the difference between UNION and UNION ALL, and when each is right.

    Show answer

    Both stack two results on top of each other. UNION then removes duplicate rows; UNION ALL keeps every row.

    Use UNION when you want a list of different values, such as "every city we have a customer or an office in, once each".

    Use UNION ALL when every row counts, such as stacking January's and February's orders before adding them up, or when duplicates can't happen anyway (each half has a different label). It is also faster: UNION has to sort or hash everything to find duplicates.

    A useful habit: write UNION ALL by default, and use UNION only when you really mean "remove duplicates".

  2. Writefrom a blank page, then run it

    Write one query that lists every person's name from both employees and customers, with a column saying which table they came from.

    Show answer

    Both halves need the same number of columns, in the same order. The label column is a fixed text value in each half. Column names come from the first half, so the second can skip .

    Tom appears twice because he signed up twice. UNION would merge those two identical rows; whether you want that depends on whether you are listing people or sign-ups.

    sql
    SELECT name, 'employee' AS source FROM employees
    UNION ALL
    SELECT name, 'customer' FROM customers
    ORDER BY source, name;

    14 rows

    namesource
    Lenacustomer
    Omarcustomer
    Priyacustomer
    Tomcustomer
    Tomcustomer
    Zoecustomer
    Ashaemployee
    Benemployee
    Chenemployee
    Daraemployee
    Eliemployee
    Fatimaemployee
    Gusemployee
    Hanaemployee
  3. Predictsay it before you run it

    How many rows does SELECT city FROM customers UNION ALL SELECT location FROM departments; return?

    Show answer

    10 rows: 6 customer cities plus 4 department locations. UNION ALL removes nothing, so the duplicate Londons and Leeds, and Zoe's NULL, all stay.

    sql
    SELECT COUNT(*) AS rows_returned
    FROM (
      SELECT city FROM customers
      UNION ALL
      SELECT location FROM departments
    );

    1 row

    rows_returned
    10
  4. Edge casesSay what happens with NULLs, ties, duplicates or no rows at all, and fix it.

    Does UNION treat two NULL cities as duplicates? Check with the first example, and explain how that differs from =.

    Show answer

    Yes. UNION (like and ) treats two NULLs as duplicates and keeps one. In the first example only Zoe's city is NULL, so add a second NULL to check: below, two NULLs go in and one comes out.

    That differs from =, where NULL = NULL is unknown, not true. The rule: for , NULL equals nothing; for removing duplicates and grouping, all NULLs count as the same.

    sql
    SELECT city FROM customers
    UNION
    SELECT NULL
    ORDER BY city;

    4 rows

    city
    NULL
    Bristol
    Leeds
    London

Practice box: write and run your answers here

Ctrl/⌘ + Enter runs it. Select part of the query to run only that part.

Step 4 Interview-ready, then prove it

Your interview answer

About 20 to 40 seconds, said out loud.

Set operators combine two result sets vertically, matching columns by position. UNION ALL appends everything; UNION also removes duplicate rows, which costs a sort or hash, so I default to UNION ALL unless duplicates must go. INTERSECT returns rows present in both results and EXCEPT returns rows in the first but not the second — a neat alternative to an when comparing id lists.

Follow-up questions

UNION vs UNION ALL?

UNION removes duplicate rows; UNION ALL keeps them all and is faster because it skips that step.

JOIN vs UNION?

A join adds columns by matching rows side by side; a union adds rows by stacking results on top of each other.

Tick each check when you can do it without notes

A topic is finished when you pass all four checks, not when you have read it. Be strict: if you had to look at the notes, it is not ticked yet.

  • Explain Say what it does and when to use it, in plain words, with no notes.
  • Write Write the query from a blank page, then run it to check.
  • Predict Read a query and say which rows it returns before you run it.
  • Edge cases Say what happens with NULLs, ties, duplicates or no rows at all, and fix it.

0 of 4 checks ticked.

Saved in this browser. Back it up or move it to another device.