00:00

MySQL UNION ALL

Last updated: 3 min read

UNION ALL combines the results of several SELECT statements and keeps every row, including duplicates. Because it doesn't have to find and remove duplicates, it is also faster than UNION. For combining facts such as payments, orders or log lines, it is almost always the right choice.

1. UNION ALL vs UNION

UNION ALL keeps every row; UNION removes duplicatesQuery A returns 500 and 750. Query B returns 500 and 1200. UNION ALL returns 500, 750, 500, 1200. UNION returns 500, 750, 1200 and has to compare rows to find the duplicate.Aamount500750Bamount5001200UNION ALLamount50075050012004 rows, no extra workUNIONamount50075012003 rows, needs de-duplication
Figure 1: UNION ALL simply appends; UNION also removes duplicate rows, which costs time.
syntax.sql
SELECT … FROM table1
UNION ALL
SELECT … FROM table2;
query.sql
SELECT customer, amount FROM upi_payments
UNION ALL
SELECT customer, amount FROM card_payments;

UNION ALL: 5 rows

customeramount
Aman500
Bela750
Aman500
Aman500
Chen1200
query.sql
SELECT customer, amount FROM upi_payments
UNION
SELECT customer, amount FROM card_payments;

UNION: duplicates removed

customeramount
Aman500
Bela750
Chen1200

2. Totals Across Tables

Aman really paid ₹500 three times. UNION would lose two of them; UNION ALL keeps the total correct:

totals.sql
SELECT customer, SUM(amount) AS total_paid, COUNT(*) AS payments
FROM (
  SELECT customer, amount FROM upi_payments
  UNION ALL
  SELECT customer, amount FROM card_payments
) all_payments
GROUP BY customer
ORDER BY total_paid DESC;

Result: 3 rows

customertotal_paidpayments
Aman15003
Chen12001
Bela7501

3. Keeping Track of the Source

with-source.sql
SELECT 'UPI'  AS method, pay_id, customer, amount, paid_on FROM upi_payments
UNION ALL
SELECT 'Card', pay_id, customer, amount, paid_on FROM card_payments
ORDER BY paid_on;

Result: 5 rows

methodpay_idcustomeramountpaid_on
UPI1Aman5002026-03-01
UPI2Bela7502026-03-02
Card1Aman5002026-03-03
Card2Chen12002026-03-04
UPI3Aman5002026-03-05

4. Merging Archive and Live Tables

Old rows are often moved to an archive table. A view with UNION ALL lets queries see both as one:

archive-view.sql
CREATE VIEW all_logs AS
SELECT id, level, msg, logged, 'archive' AS src FROM logs_archive
UNION ALL
SELECT id, level, msg, logged, 'live' FROM logs_live;

SELECT level, COUNT(*) AS entries FROM all_logs GROUP BY level ORDER BY entries DESC;

Result: 3 rows

levelentries
ERROR3
WARN1
INFO1
query.sql
SELECT msg, logged, src FROM all_logs WHERE level = 'ERROR' ORDER BY logged;

Result: 3 rows

msgloggedsrc
disk full2026-01-10archive
timeout2026-03-01live
disk full2026-03-05live

5. Building Small Lists of Rows

UNION ALL of constant SELECTs is a quick way to make a small inline table, for example to report categories with zero rows:

inline-table.sql
SELECT l.level, COUNT(a.id) AS entries
FROM (SELECT 'ERROR' AS level UNION ALL SELECT 'WARN' UNION ALL SELECT 'INFO' UNION ALL SELECT 'DEBUG') l
LEFT JOIN all_logs a ON a.level = l.level
GROUP BY l.level;

Result: 4 rows

levelentries
ERROR3
WARN1
INFO1
DEBUG0

6. Why UNION ALL Is Faster

For UNION, MySQL must put all rows into a temporary table with a unique key to discard duplicates. UNION ALL can usually stream rows straight to the client without a temporary table.

query.sql
EXPLAIN SELECT customer FROM upi_payments UNION SELECT customer FROM card_payments;

UNION: extra UNION RESULT step with a temporary table

idselect_typetableExtra
1PRIMARYupi_paymentsNULL
2UNIONcard_paymentsNULL
3UNION RESULT<union1,2>Using temporary
query.sql
EXPLAIN SELECT customer FROM upi_payments UNION ALL SELECT customer FROM card_payments;

UNION ALL: no de-duplication step

idselect_typetableExtra
1PRIMARYupi_paymentsNULL
2UNIONcard_paymentsNULL

7. When to Use Which

Use UNION ALL when…Use UNION when…
Rows are facts that can legitimately repeat (payments, events)You want a list of distinct values (unique cities, emails)
The parts can't overlap (different years, different tables)The same row could come from several parts and must appear once
Performance mattersResult size matters more than speed

8. Summary

  • UNION ALL appends results and keeps duplicates; UNION removes them.
  • Same column rules as UNION: same count, matched by position.
  • Use UNION ALL for totals and for combining archive and live data.
  • UNION ALL avoids the de-duplication temp table, so it's faster.