A LEFT JOIN returns all rows from the left table, and the matching rows from the right table. When a row in the left table has no match in the right table, the right-side columns are filled with NULL. No row from the left table is ever excluded.
This makes LEFT JOIN ideal for finding records that exist in one table but may or may not have related records in another — for example, all customers including those who have never placed an order.
SELECT columns
FROM table_a AS a
LEFT JOIN table_b AS b ON a.id = b.foreign_key;
LEFT JOIN and LEFT OUTER JOIN are identical — the word OUTER is optional in MySQL.
Get all customers, with their order details where available:
SELECT c.name, c.city, o.id AS order_id, o.amount
FROM customers AS c
LEFT JOIN orders AS o ON c.id = o.customer_id;
| name | city | order_id | amount |
|---|---|---|---|
| Rahim Uddin | Dhaka | 1 | 2500.00 |
| Rahim Uddin | Dhaka | 2 | 1200.00 |
| Sara Begum | Chittagong | NULL | NULL |
| Karim Ali | Sylhet | 3 | 4800.00 |
| Nila Akter | Dhaka | NULL | NULL |
Sara Begum and Nila Akter are included — even though they have no orders. Their order_id and amount columns show NULL. The orphaned order (customer_id=6) is still excluded because it has no matching customer in the left table.
One of the most powerful uses of LEFT JOIN is finding records in the left table that have no corresponding entry in the right table. Filter for NULL on the right-side column after the join:
-- Customers who have never placed an order
SELECT c.name, c.city
FROM customers AS c
LEFT JOIN orders AS o ON c.id = o.customer_id
WHERE o.id IS NULL;
| name | city |
|---|---|
| Sara Begum | Chittagong |
| Nila Akter | Dhaka |
LEFT JOIN ... WHERE right_table.id IS NULL is the standard way to find records in one table that have no related records in another. This is a very common reporting pattern.
Count the number of orders per customer, including customers with zero orders:
SELECT c.name, COUNT(o.id) AS total_orders
FROM customers AS c
LEFT JOIN orders AS o ON c.id = o.customer_id
GROUP BY c.id, c.name
ORDER BY total_orders DESC;
| name | total_orders |
|---|---|
| Rahim Uddin | 2 |
| Karim Ali | 1 |
| Sara Begum | 0 |
| Nila Akter | 0 |
Using COUNT(o.id) instead of COUNT(*) is important here — COUNT(o.id) skips NULL values, correctly returning 0 for customers with no orders, while COUNT(*) would return 1 for those rows.
LEFT JOIN returns all rows from the left table, plus matched rows from the right.NULL.LEFT JOIN keyword.WHERE right_table.column IS NULL after a LEFT JOIN to find unmatched records.COUNT() with a left join, use COUNT(right_table.id) — not COUNT(*) — to get accurate zero counts.LEFT JOIN, which keeps all rows from the right table instead.