UNION vs UNION ALL in SQL: Which One and Why
On this page 10 sections ▾
Both stack the results of two queries on top of each other. The only difference is what happens to duplicates: UNION removes them, UNION ALL keeps them. That one difference decides both the answer you get and how long the query takes.
Everything below runs against the sample database, so you can see the row counts change as you switch between them.
The difference in two queries
The customers table has a city, the departments table has a location. Stack them:
SELECT city AS place FROM Customers
UNION ALL
SELECT location FROM Departments;
| place |
|---|
| London |
| Austin |
| Osaka |
| Arusha |
| Lima |
| Arequipa |
| Beirut |
| Bergen |
| Bengaluru |
| London |
| New York |
| Berlin |
| Singapore |
● 13 rows · produced by running this query on the sample database
Every row from both queries, in order. Now the same thing with UNION:
SELECT city AS place FROM Customers
UNION
SELECT location FROM Departments;
| place |
|---|
| Bengaluru |
| London |
| New York |
| Berlin |
| Singapore |
| Austin |
| Osaka |
| Arusha |
| Lima |
| Arequipa |
| Beirut |
| Bergen |
● 12 rows · produced by running this query on the sample database
One row fewer, because one place appears in both tables and UNION collapsed the two copies into one. That is the entire difference. Everything else on this page follows from it.
What UNION costs to do that
To know whether a row is a duplicate, the database has to compare every row against every row it has already produced — which means sorting or hashing the combined result before it can return anything. UNION ALL can stream rows out as it finds them.
| UNION | UNION ALL | |
|---|---|---|
| Duplicate rows | removed | kept |
| Extra work | sorts or hashes the whole result | none |
| Can start returning rows immediately | no | yes |
| Row order of the result | not guaranteed (often sorted as a side effect) | not guaranteed |
| Right default | only when duplicates are wrong | yes |
Do not rely on UNION to sort your rows
De-duplicating often sorts the result as a by-product, so a UNION can look reliably ordered and then stop being ordered when the database picks a hash-based plan instead. If you want an order, write an ORDER BY.
The rules both must obey
Two queries can only be stacked if their result shapes line up:
- The same number of columns. Non-negotiable.
- Compatible types, column by column. Position matters, names do not — the first column of the second query lands under the first column of the first query whatever it is called.
- The column names come from the first query. Alias there if you want a readable heading; aliasing in the second query has no effect on the output.
Break the first rule and a real database refuses the query outright, with a message about the operands not having the same number of columns:
SELECT city FROM Customers
UNION
SELECT dept_id, dept_name FROM Departments;
That block is marked as intentionally wrong rather than given a Run button, and for an honest reason: the in-browser engine here is lenient about it and returns something anyway, while PostgreSQL, MySQL, SQL Server and Oracle all reject it. Trust the real databases — matching the column lists is a hard rule.
Where ORDER BY goes
One ORDER BY, at the very end, applying to the combined result:
SELECT city AS place FROM Customers
UNION
SELECT location FROM Departments
ORDER BY place;
| place |
|---|
| Arequipa |
| Arusha |
| Austin |
| Beirut |
| Bengaluru |
| Bergen |
| Berlin |
| Lima |
| London |
| New York |
| Osaka |
| Singapore |
● 12 rows · produced by running this query on the sample database
An ORDER BY inside either branch is either an error or pointless, because the branches are combined before the final sort. The same goes for LIMIT: to limit the combined result, put it after the last branch; to limit a branch, wrap that branch in a subquery.
The pattern you will actually use: labelled UNION ALL
Stacking two different kinds of thing into one list, with a column saying which is which, is the most common real use of UNION ALL:
SELECT first_name AS person_name, 'Employee' AS source FROM Employees
UNION ALL
SELECT contact, 'Customer' FROM Customers
ORDER BY source, person_name;
| person_name | source |
|---|---|
| Alice Turner | Customer |
| Ben Whitaker | Customer |
| Carlos Rojas | Customer |
| Eva Kalnina | Customer |
| Ingrid Solberg | Customer |
| Neema Juma | Customer |
| Rami Nassar | Customer |
| Yuki Mori | Customer |
| Ananya | Employee |
| Chen | Employee |
| Daniel | Employee |
| Grace | Employee |
| Hiroshi | Employee |
| Isabela | Employee |
| Leila | Employee |
● first 15 of 20 rows · produced by running this query on the sample database
Two things worth copying from that query. The literal 'Employee' and 'Customer' are ordinary expressions, so a constant is a perfectly good column. And UNION ALL is correct here rather than a habit: if an employee and a customer happen to share a first name, they are two different people and both rows must survive. UNION would silently merge them — a real bug, not a tidier list.
UNION versus a JOIN
This is the follow-up interview question, and the answer is a single sentence: a join adds columns, a union adds rows.
| JOIN | UNION | |
|---|---|---|
| Combines | columns from two tables, side by side | rows from two results, stacked |
| Matched by | an ON condition | nothing - position in the column list |
| Result is | wider | longer |
| Use it for | attaching related information to a row | putting similar things in one list |
If you need a customer’s name next to their order, that is a join. If you need this month’s orders and last month’s archived orders in one list, that is a union. They are not alternatives.
INTERSECT and EXCEPT
The same family, less often used and worth knowing exist. INTERSECT returns the rows that appear in both results; EXCEPT (called MINUS in Oracle) returns the rows in the first result that are not in the second. Both de-duplicate, like UNION. MySQL only added them in version 8.0.31, so on older MySQL the equivalents are an EXISTS or NOT EXISTS subquery, which is usually clearer anyway.
Practice this topic
Reading explains the idea; producing it yourself is what makes it stick. These exercises use exactly what this page covers, and your answer is checked by running it against the same sample database:
- One combined contact listMedium
- Which countries do we sell to?Easy
- How many customers do we have?Easy
Frequently asked questions
What is the difference between UNION and UNION ALL?
UNION removes duplicate rows from the combined result; UNION ALL keeps every row from both queries. Because UNION has to compare rows to find duplicates, it must sort or hash the whole result first, which makes it slower and stops it streaming rows out as it goes.
Which is faster, UNION or UNION ALL?
UNION ALL, always. It concatenates the two results with no extra work, while UNION additionally sorts or hashes them to remove duplicates. Use UNION ALL unless duplicate rows would be wrong for your purpose.
Do the two queries in a UNION need the same columns?
They need the same number of columns and compatible types in the same positions. The names do not have to match - the result takes its column names from the first query, so alias there. Mismatched column counts are rejected by every major database.
Where do I put ORDER BY in a UNION query?
Once, at the very end, after the final branch. It sorts the combined result. An ORDER BY inside a branch is either rejected or has no effect, because the branches are combined before the sort happens.
What is the difference between UNION and JOIN?
A JOIN combines columns from two tables side by side using an ON condition, making the result wider. A UNION stacks rows from two results on top of each other, making it longer. They solve different problems and are not alternatives.
Does UNION sort the result?
Not by contract. Removing duplicates often sorts the rows as a side effect, so the output can look ordered, but the database is free to use a hashing plan instead and return them in any order. Add an explicit ORDER BY if the order matters.
Related reading
About the author
SQL Practice
SQL Practice publishes free SQL tutorials, an in-browser playground and 42 practice exercises, built so you can run what you read. Every runnable example in our tutorials is executed against the site’s sample database before it is published. Read how we keep tutorials accurate, or report a mistake.