LEFT JOIN

Keep all left rows — even when there's no match on the right

Intermediate 14 minLEFT JOINOUTER JOIN

Keeping All Left Rows

LEFT JOIN returns all rows from the left table, plus matched rows from the right. When there's no match, the right-side columns fill with NULL instead of dropping the row entirely. Here's what makes it different:

Preserves unmatched rows — INNER JOIN silently drops rows without matches on both sides. LEFT JOIN keeps every left row intact — essential for finding missing data like customers without orders or products without reviews.
The anti-join patternLEFT JOIN + WHERE right_table.id IS NULL finds rows that exist on the left but have no match on the right. This powerful pattern answers the question "what's missing?" in a single query.
Table order mattersFROM customers LEFT JOIN orders keeps all customers in the result. FROM orders LEFT JOIN customers keeps all orders instead. Choose which table goes on the left based on what you want to preserve.
Knowledge Canvas

How LEFT JOIN Works

Keep all rows from the left table

AB
  • ALL left rows survive — even without a match
  • Unmatched right columns fill with NULL
  • Table order matters: left table = preserved table
  • LEFT OUTER JOIN = LEFT JOIN (OUTER is optional)

The Anti-Join Pattern

Find what's missing

  • LEFT JOIN + WHERE right.id IS NULL = find unmatched rows
  • Customers with no orders: LEFT JOIN orders ON ... WHERE orders.id IS NULL
  • Products without reviews, users without logins, etc.
  • Cleaner alternative: NOT EXISTS (but anti-join is more common)
SELECT c.name
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.id IS NULL;

NULL in LEFT JOIN

Understanding NULL-filled columns

  • Unmatched rows get NULL in ALL right-table columns
  • COUNT(right.col) correctly returns 0 for unmatched rows
  • SUM(right.col) returns NULL for unmatched — wrap in COALESCE
  • WHERE on right columns filters AFTER join — may eliminate unmatched rows

LEFT JOIN Mistakes

Traps that turn LEFT JOIN into INNER JOIN

  • WHERE right_table.col = value → eliminates NULLs → becomes INNER JOIN
  • Move right-table filters to the ON clause instead
  • Forgetting table order: FROM orders LEFT JOIN customers ≠ FROM customers LEFT JOIN orders
  • Multiple LEFT JOINs can create unexpected row multiplication

LEFT vs INNER JOIN

Key behavioral differences

LEFT JOIN: preserves all left rows
INNER JOIN: drops unmatched rows
Unmatched → NULL columns
Unmatched → row disappears
Result count ≥ left table rows
Result count ≤ smaller table
Use for: inclusive reports, find gaps
Use for: linked data, matched records
Syntax
Syntax Template
1-- Standard LEFT JOIN — keep all left rows
2SELECT
3 a.col,
4 b.col
5FROM table_a a
6LEFT JOIN table_b b
7 ON a.key = b.key;
8
9-- Anti-join pattern — find unmatched left rows
10SELECT
11 a.*
12FROM table_a a
13LEFT JOIN table_b b
14 ON a.key = b.key
15WHERE b.key IS NULL;
LEFT JOINAll left rows + matched right rows (or NULL)
Anti-joinLEFT JOIN + WHERE right.id IS NULL = find unmatched rows
Sample Data
customers
12 rows
idname
C1001Aarav Sharma
C1002Sara Chen
C1003James Wilson
C1004Maria Garcia
C1005Yuki Tanaka
C1006Priya Patel
C1007Alex Johnson
C1008Chen Wei
C1009Emma Brown
C1010Omar Hassan
C1011Lena Muller
C1012Ravi Kumar
orders
12 rows
idcustomer_idtotal
5001C100159.98
5002C1002449
5003C100112.5
5004C100389.99
5005C1006245
5006C1005159
5007C100445.5
5008C100979
5009C1012425
5010C100718.99
5011C1008134
5012C101065.5
products
10 rows
idnamecategorypricestock
P101Wireless MouseElectronics24.99150
P102Office DeskFurniture18925
P103LED Desk LampFurniture45.580
P104USB-C CableElectronics12.99500
P105Bluetooth SpeakerElectronics7960
P106Office ChairFurniture9515
P107Coffee MakerAppliances89.9940
P108Notebook SetStationery8.5200
P109Wireless HeadphonesElectronics15930
P110Standing DeskFurniture4258
reviews
12 rows
idproduct_idcustomer_idratingcomment
7001P101C10015Excellent mouse, very comfy
7002P101C10034NULL
7003P101C10053Good but battery drains fast
7004P102C10025Solid build, worth every rupee
7005P102C10064Spacious — fits two monitors
7006P103C10044NULL
7007P104C10075Just works, durable braided cable
7008P105C10095Great sound for the price
7009P105C10124Battery could be better
7010P107C10083NULL
7011P108C10115Good notebooks, smooth paper
7012P109C10015Premium feel, noise cancellation is real

Worked Example

Show all customers and their order count, including those with zero orders.

SQL
1SELECT
2 c.name,
3 COUNT(o.id) AS order_count
4FROM customers c
5LEFT JOIN orders o
6 ON c.id = o.customer_id
7GROUP BY
8 c.id,
9 c.name
10ORDER BY
11 order_count DESC;
LEFT JOIN keeps every customer. Those without orders get NULL for all order columns. COUNT(o.id) counts non-NULL values, so customers with no orders correctly show 0.
Output
5 rows
nameorder_count
Aarav Sharma2
Sara Chen1
James Wilson1
Maria Garcia1
Yuki Tanaka1

Key Concepts

1All left rows survive — unmatched right columns fill with NULL
2LEFT JOIN + WHERE right.id IS NULL = find what's missing (anti-join)
3Table order matters — the left table is the one being preserved
4INNER JOIN drops unmatched rows silently — LEFT JOIN shows them

Pro Tip

INNER JOIN silently drops unmatched rows. LEFT JOIN preserves them — essential when you need to see what's missing or incomplete.

When to Use

Customers with no orders, products without reviews, gaps in data coverage, inclusive reports showing all items even without activity.

Challenge

Solve the problem below

Find products that have NEVER been reviewed. Show just the product name. (Hint: LEFT JOIN + WHERE IS NULL)

Your Query