Lesson 3 of 6

JOINs

Back in lesson 1 you split a library into authors and books tables instead of one giant sheet — great for avoiding duplicated data, but now you've got a new problem: what if you want a list of book titles with their author's name printed right next to them? That data lives in two separate tables. A JOIN is how you glue matching rows from two tables back together for a single query.

💡 The Bottom Line

A JOIN combines rows from two tables based on a matching column — typically a foreign key matching a primary key. INNER JOIN returns only rows that match in both tables; LEFT JOIN returns every row from the left table, filling in NULL for any right-side columns that have no match. Splitting data into separate tables only pays off because JOIN lets you stitch it back together whenever you need to.

Why you need a join

Picture two tables: customers and orders, where each order references the customer who placed it.

customers
+----+---------+
| id | name    |
+----+---------+
| 1  | Priya   |
| 2  | Marco   |
| 3  | Aisha   |
+----+---------+

orders
+----+-------------+--------+
| id | customer_id | total  |
+----+-------------+--------+
| 1  | 1           | 42.00  |
| 2  | 1           | 18.50  |
| 3  | 2           | 99.00  |
+----+-------------+--------+

Notice Aisha has no matching row in orders at all — she hasn't ordered yet. That detail matters for the two join types below.

INNER JOIN: only the matches

INNER JOIN returns a row only when both tables have a match on the join condition. Customers with zero orders simply won't appear:

SELECT customers.name, orders.total
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
name   | total
-------+-------
Priya  | 42.00
Priya  | 18.50
Marco  | 99.00

Priya appears twice, once per order — a join produces one output row per matching pair, not one row per customer. Aisha doesn't appear at all, since she has no matching row in orders.

🙋 There Are No Dumb Questions

Q: Why does Priya show up twice? Doesn't that duplicate her data?
A: It looks like duplication, but it isn't — her name isn't stored twice in the database, only in this particular result set, because she has two matching orders. A join's job is to produce one row per matching pair of (customer, order); if a customer has two orders, that's two pairs.

LEFT JOIN: keep everything on the left, matched or not

Want Aisha to show up anyway, even with no orders? Use LEFT JOIN — it keeps every row from the table on the left, and fills in NULL wherever there's no match on the right:

SELECT customers.name, orders.total
FROM customers
LEFT JOIN orders ON customers.id = orders.customer_id;
name   | total
-------+-------
Priya  | 42.00
Priya  | 18.50
Marco  | 99.00
Aisha  | NULL

⚠️ Watch Out

Forgetting the ON condition (or joining on the wrong columns) doesn't error out — it silently pairs every row in one table with every row in the other, producing a result far bigger and more nonsensical than you intended. Always double-check the columns in your ON clause actually represent the same real-world thing (a foreign key matching its primary key).

The mental model

Think of a join as laying the two tables side by side and drawing a line between rows that match on the join column. INNER JOIN keeps only the rows with a line connecting them; LEFT JOIN keeps every row from the left table, whether or not it has a line, padding the missing side with NULL.

🔧 Try It Yourself

Using the customers and orders tables above, write a LEFT JOIN query that returns each customer's name alongside the total number of orders they've placed — for customers with no orders, that count should show as 0 rather than being omitted. (Hint: you'll want this lesson's JOIN combined with next lesson's COUNT and GROUP BY — sketch the join first, and revisit this after the next lesson.)

✅ Quick Check

You run an INNER JOIN between customers and orders. Aisha has never placed an order. What happens to her row?


Next up: once you can join related tables together, the natural next step is summarizing them — counting orders, totaling revenue, averaging prices. That's aggregation and GROUP BY.

← Back to
Next →