MySQL Left Join

LEFT JOIN keeps every row from the left table, filling in NULLs for any right-table columns that don't have a match.

What Makes LEFT JOIN Different

A LEFT JOIN starts from the table listed first - the 'left' table - and keeps every one of its rows in the result, no matter what. For each row, MySQL looks for a matching row in the second table using the ON condition; if it finds one, the right-hand columns are filled in normally, and if it finds none, those columns come back as NULL rather than the row being dropped. This makes LEFT JOIN the tool of choice whenever the left table's completeness matters more than the match, such as 'every customer, whether or not they've ordered anything yet'.

Every customer, with order info if any exists

SELECT c.customer_id, c.name, o.order_id, o.total_amount
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id;

Finding Rows With No Match

Because unmatched rows come back with NULL in every right-table column, you can isolate them with a WHERE ... IS NULL check on a column that could never legitimately be NULL, such as the right table's primary key. This 'anti-join' pattern - LEFT JOIN plus an IS NULL filter - is the standard way to answer 'which rows exist on the left that have nothing on the right'.

Customers who have never placed an order

SELECT c.customer_id, c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;

Counting Related Rows Including Zeros

A plain INNER JOIN with GROUP BY silently drops customers who have no orders, since there's no row to count. Switching to LEFT JOIN keeps them in the result with a count of zero, as long as you use COUNT(o.order_id) - which only counts non-NULL values - rather than COUNT(*), which would count the single NULL-filled placeholder row as one.

Number of orders per customer, including zero

SELECT c.customer_id, c.name, COUNT(o.order_id) AS order_count
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;
  • table_a LEFT JOIN table_b is equivalent to table_b RIGHT JOIN table_a - the two keywords describe the same shape from opposite directions.
  • Every row from the left table appears at least once, and possibly more than once if it matches several right-table rows.
  • Placing a right-table filter in the ON clause keeps unmatched left rows in the result; placing the same filter in WHERE can silently remove them.
  • LEFT JOIN is the standard pattern for 'all X, with optional Y' reports.
Left row (customers)Right row (orders)Result
Aditi (id=1)order 501, order 5022 rows, both showing Aditi's name
Raghav (id=2)no matching orders1 row, all order columns NULL
Note: Read the query left to right out loud - 'customers LEFT JOIN orders' literally means 'keep all customers, join in orders where they exist' - and the SQL usually matches your intent.
Note: Adding a right-table condition to WHERE instead of ON, like WHERE o.status = 'shipped', filters out the NULL-filled rows for unmatched customers too, because NULL = 'shipped' is never true - this quietly turns your LEFT JOIN back into something behaving like an INNER JOIN. Move that condition into the ON clause if you want unmatched rows to survive.