Lesson 6 of 10 · 10 min · 2 hands-on steps
Combining Tables with JOIN
See exactly how INNER and LEFT JOIN match rows, then write your own.
Why data lives in separate tables
Instead of copying a customer's name onto every order, orders stores a customer_id that points to a row in customers. That pointer is called a foreign key. A JOIN follows it.
See it happen
Switch between INNER and LEFT JOIN and watch which rows survive:
SELECT c.name, o.item FROM customers c INNER JOIN orders o ON o.customer_id = c.id;
| id | name |
|---|---|
| 1 | Amara |
| 2 | Bo |
| 3 | Carla |
| 4 | Dev |
| id | customer_id | item |
|---|---|---|
| 10 | 1 | Keyboard |
| 11 | 1 | Mouse |
| 12 | 3 | Monitor |
| 13 | 9 | Cable |
| name | item |
|---|---|
| Amara | Keyboard |
| Amara | Mouse |
| Carla | Monitor |
INNER JOIN keeps only rows that match on both sides. Dev has no orders, and order 13 has no customer, so both disappear.
Writing joins
SELECT c.name, o.ordered_on, o.quantity FROM orders o JOIN customers c ON c.id = o.customer_id;
orders ogives the table a short nickname (an alias)ONsays how the rows match
LEFT JOIN to find what's missing
SELECT c.name, COUNT(o.id) AS orders FROM customers c LEFT JOIN orders o ON o.customer_id = c.id GROUP BY c.id ORDER BY orders DESC;
"Customers with no orders" and "products never sold" are classic interview and real-world questions. The answer is almost always a LEFT JOIN plus IS NULL.
🧪 Practice: 2 steps
0 / 2 doneStep 1 of 2 · Who ordered what
Return each order's customer name and product name (columns customer and product), ordered by order id.
Tables: orders(id, customer_id, product_id, …), customers(id, name, …), products(id, name, price).
SELECT o.id, o.customer_id, o.product_id FROM orders o;
Output appears here. Press Run or Ctrl/⌘ + Enter.
Step 2 of 2 · Customers who never ordered
Return the name of every customer who has no orders at all.
SELECT c.name, o.id FROM customers c LEFT JOIN orders o ON o.customer_id = c.id;
Output appears here. Press Run or Ctrl/⌘ + Enter.
✅ Check your understanding
Which JOIN keeps every row from the left table, even without a match?
Create a free account to track your progress.