SQL course menu
SQL FULL OUTER JOIN: Keep All Rows From Both Tables
Learn SQL FULL OUTER JOIN with diagrams and examples: keep matched and unmatched rows from both tables, find mismatches on either side, and emulate FULL JOIN in MySQL with UNION.
On this page
A FULL OUTER JOIN keeps every row from both tables. Rows that match are combined; rows without a partner on either side still appear, with NULLs for the missing side. It is the join for comparing two lists and seeing everything: matches, and mismatches in both directions.
The example tables#
customers
orders
Syntax#
SELECT columns
FROM table_a
FULL OUTER JOIN table_b
ON table_a.column = table_b.column;FULL JOIN is a shorter way to write the same thing.
Example#
SELECT c.name, o.order_id, o.amount
FROM customers c
FULL OUTER JOIN orders o
ON o.customer_id = c.customer_id;name | order_id | amount
------+----------+-------
Asha | 101 | 250
Asha | 102 | 120
Ravi | 103 | 560
Meera | NULL | NULL
John | NULL | NULL
NULL | 104 | 90The result contains three kinds of rows:
In other words, FULL OUTER JOIN = INNER JOIN + unmatched left rows + unmatched right rows.
Find mismatches on both sides#
Keep only rows where one side is missing. This is a classic reconciliation query, for example comparing a bank statement with your own records:
SELECT c.customer_id, c.name, o.order_id, o.customer_id AS order_customer
FROM customers c
FULL OUTER JOIN orders o
ON o.customer_id = c.customer_id
WHERE c.customer_id IS NULL
OR o.order_id IS NULL;customer_id | name | order_id | order_customer
------------+-------+----------+---------------
3 | Meera | NULL | NULL
4 | John | NULL | NULL
NULL | NULL | 104 | 5Summarising with a FULL JOIN#
Because unmatched rows have NULLs, combine COALESCE with aggregates to produce a clean report:
SELECT COALESCE(c.name, 'Unknown customer') AS customer,
COALESCE(SUM(o.amount), 0) AS total
FROM customers c
FULL OUTER JOIN orders o
ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name
ORDER BY total DESC;customer | total
-----------------+------
Ravi | 560
Asha | 370
Unknown customer | 90
Meera | 0
John | 0Every customer and every order is accounted for, and the totals add up to all revenue (1,020).
MySQL: emulate FULL OUTER JOIN#
MySQL does not support FULL OUTER JOIN. Combine a LEFT JOIN and a RIGHT JOIN with UNION, which also removes the duplicate matched rows:
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
UNION
SELECT c.name, o.order_id
FROM customers c
RIGHT JOIN orders o ON o.customer_id = c.customer_id;PostgreSQL, SQL Server, Oracle and SQLite 3.39+ support FULL OUTER JOIN directly.
Common mistakes#
Practice#
Practice exercise
How many rows does customers FULL OUTER JOIN orders return, and how many of them have a NULL in o.order_id? Explain using the three kinds of rows.
Show hint
Count matched pairs, unmatched customers, and unmatched orders separately.
Show solution
- Matched pairs: 3 (Asha ×2, Ravi ×1)
- Customers with no order: 2 (Meera, John), with
o.order_id=NULL - Orders with no customer: 1 (order 104)
Total: 3 + 2 + 1 = 6 rows, of which 2 have a NULL order_id.
Key takeaway#
Finished this lesson?