JOINs without the panic
JOINs are where most people freeze. They look scary. They are not. A JOIN is just glue between two tables, and there are really only two flavours you need to remember.
Once this clicks, your queries go from "list of stuff" to "actual answers to business questions." This is the unlock.
Why we even need JOINs
Your customers live in a customers table. Their orders live in an orders table. The orders table just has a customer_id, not the full customer name. So to print "Priya placed an order for 450 rupees," you need to glue the two tables together using that ID.
That gluing is a JOIN. The column you glue on is usually an ID.
INNER JOIN: only matches
The default. Returns rows where the join condition matches in both tables.
SELECT c.name, o.total
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id;candoare aliases, short nicknames for the tables. Saves typing and clarifies which column came from where.ONsays how the tables connect.- If a customer has zero orders, they do not show up. INNER JOIN is strict.
LEFT JOIN: keep everyone on the left
When you want all rows from the left table, even if there is no match on the right.
SELECT c.name, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;Customers with no orders still appear, but o.total will be NULL for them. This is exactly how you answer questions like "which customers have not ordered in six months."
Rule of thumb: start with INNER JOIN. If you find rows missing that you expected to see, switch to LEFT JOIN.
RIGHT JOIN: yes it exists, no you don't need it
RIGHT JOIN is LEFT JOIN with the tables flipped. Anything you can write as RIGHT JOIN, you can write as LEFT JOIN by swapping the table order. Every team I have worked on, by convention, just uses LEFT JOIN. Less mental gymnastics.
Multi-table JOINs
You can keep going. Customers, orders, restaurants:
SELECT c.name, r.name AS restaurant, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN restaurants r ON r.id = o.restaurant_id;Each JOIN adds one more table. Build it one JOIN at a time, run it, check the count makes sense, then add the next one. Do not write all three at once and pray.
The cartesian product mistake
Forget the ON clause and SQL will happily pair every row in table A with every row in table B. 10,000 customers and 50,000 orders becomes 500 million rows. Your query hangs. Your DB cries.
Always include
ON. If your row count explodes, that is the first thing to check. I have killed a production query at 2am for exactly this reason.
Try it on the right
Three JOIN assignments. Use aliases. Read the ON clause carefully. Next: GROUP BY and the aggregate functions that turn rows into insights.
Free tools you can use while you learn
Common questions
Q.When should I use INNER JOIN vs LEFT JOIN?›
Q.Why is my JOIN returning duplicate rows?›
Q.How many tables can I JOIN at once?›
Watching quietly. Tap me if you want a tip.
Try this (0 of 2 done)
- 1
Show each delivered order with the customer's name and the restaurant's name.
hint
Join customers AND restaurants onto orders.
show answer
SELECT c.name AS customer, r.name AS restaurant, o.total FROM orders o JOIN customers c ON c.id = o.customer_id JOIN restaurants r ON r.id = o.restaurant_id WHERE o.status = 'delivered'; - 2
Show every customer with their orders. Include customers who haven't ordered yet (LEFT JOIN).
hint
LEFT JOIN orders ON orders.customer_id = customers.id
show answer
SELECT c.name, o.id AS order_id FROM customers c LEFT JOIN orders o ON o.customer_id = c.id;