SQL Tutorial › Joins & Set Operators › UNION & UNION ALL

SQL UNION and UNION ALL

IntermediateLesson 38 of 699 min read5 queries run on MySQL 8.4

A join puts columns side by side; UNION stacks rows on top of each other. Use it to merge similar lists from different tables or conditions: all people in a mailing list (customers and employees), or a report row plus a total row. UNION removes duplicates, UNION ALL keeps them.

Advertisement
In this lesson
  • Stack the results of two queries with UNION
  • Know the column rules
  • Choose between UNION and UNION ALL
  • Sort and label the combined result

UNION syntax

MySQL
SELECT column1, column2 FROM table1UNION [ALL]SELECT column1, column2 FROM table2[ORDER BY ...];

Rules:

  • every SELECT must return the same number of columns;
  • columns are matched by position, and should have compatible types;
  • the column names come from the first SELECT;
  • one ORDER BY at the very end sorts the combined result.

Combine two lists

Every city where we have an employee or a customer:

SQL
SELECT city FROM employeesUNIONSELECT city FROM customersORDER BY city;
ResultMySQL 8.4
city
Bengaluru
Chennai
Delhi
Goa
Hyderabad
Kolkata
Mumbai
Pune
8 rows in set
How this query works, step by step
  1. The first query returns 12 employee cities, the second 7 customer cities.
  2. UNION merges them and removes duplicates, such as Mumbai, which appears in both.
  3. ORDER BY city sorts the final list.

UNION ALL keeps duplicates

SQL
SELECT city FROM employeesUNION ALLSELECT city FROM customersORDER BY city;
ResultMySQL 8.4
city
Bengaluru
Bengaluru
Bengaluru
Bengaluru
Bengaluru
Chennai
Delhi
Delhi
Goa
Hyderabad
Kolkata
Kolkata
Mumbai
Mumbai
Mumbai
Mumbai
Pune
Pune
Pune
19 rows in set
How this query works, step by step
  1. UNION ALL simply appends the second result to the first: 12 + 7 = 19 rows.
  2. No duplicate check is done, so it is faster. Use it whenever duplicates are impossible or wanted.

Label where each row came from

A contact list from two tables, with a type column:

SQL
SELECT CONCAT(first_name, ' ', last_name) AS name, city, 'Employee' AS typeFROM employeesWHERE city = 'Mumbai'UNION ALLSELECT customer_name, city, 'Customer'FROM customersWHERE city = 'Mumbai'ORDER BY type, name;
ResultMySQL 8.4
namecitytype
Ananya SharmaMumbaiCustomer
Meera KapoorMumbaiEmployee
Neha GuptaMumbaiEmployee
Vikram SinghMumbaiEmployee
4 rows in set
How this query works, step by step
  1. Both queries return three columns: a name, a city and a constant label.
  2. The second query’s columns have no aliases; the names name, city and type come from the first query.
  3. ORDER BY type, name uses those names.

A total row

SQL
SELECT category, SUM(stock) AS unitsFROM productsGROUP BY categoryUNION ALLSELECT 'TOTAL', SUM(stock)FROM products;
ResultMySQL 8.4
categoryunits
Electronics165
Furniture65
Stationery550
TOTAL780
4 rows in set

Column count must match

MySQL
SELECT first_name, city FROM employeesUNIONSELECT customer_name FROM customers;
ResultMySQL 8.4
ERROR 1222 (21000): The used SELECT statements have a different number of columns

UNION vs JOIN

UNIONJOIN
Combinesrows (vertically)columns (horizontally)
Needssame number of columnsa matching condition
Typical usemerge similar listsrelate different tables

Exercise: All people named with A

List every employee first name and every customer name that starts with “A”, in one alphabetical list without duplicates.

Expected resultMySQL 8.4
name
Amit
Ananya Sharma
Arjun
Asha
4 rows in set
Hint 1

Two SELECTs with LIKE 'A%', combined with UNION.

Quick quiz

1. What is the difference between UNION and UNION ALL?

2. Where do the column names of a UNION result come from?

3. Which is faster when duplicates do not matter?

UNION FAQ

What does UNION do in SQL?

It combines the result rows of two or more SELECT statements into one result and removes duplicates.

Can I use ORDER BY with UNION?

Yes, once, at the end, to sort the combined result. To sort or limit one part only, wrap it in parentheses.

Do the column names have to match in a UNION?

No. Only the number of columns and compatible types matter; the result uses the first query’s names.