In a relational database, data is intentionally spread across multiple tables. A customers table holds customer information. An orders table holds order information. They are separate — but related. A JOIN is the SQL mechanism that brings related rows from two or more tables together into a single result set, based on a matching column.
Without joins, you would have to run multiple separate queries and combine the results manually in your application code. With joins, MySQL does the work for you in one query.
Good database design avoids storing the same information in multiple places. Instead of repeating a customer's name and address inside every order row, you store the customer once in a customers table and reference them by ID in the orders table. When you need a report that shows both the order details and the customer name, a JOIN reunites that data.
All JOIN lessons in this section use the following two tables:
| id | name | city |
|---|---|---|
| 1 | Rahim Uddin | Dhaka |
| 2 | Sara Begum | Chittagong |
| 3 | Karim Ali | Sylhet |
| 4 | Nila Akter | Dhaka |
| id | customer_id | amount | order_date |
|---|---|---|---|
| 1 | 1 | 2500.00 | 2025-06-01 |
| 2 | 1 | 1200.00 | 2025-06-05 |
| 3 | 3 | 4800.00 | 2025-06-08 |
| 4 | 6 | 900.00 | 2025-06-10 |
Notice that:
id=1 (Rahim) has two orders.id=3 (Karim) has one order.id=2 and id=4 have no orders.id=4 references customer_id=6, which does not exist in the customers table.These gaps and mismatches are exactly what makes the different join types behave differently.
The general pattern for any join is:
SELECT columns
FROM table_a
[JOIN TYPE] JOIN table_b ON table_a.column = table_b.column;
The ON clause defines the relationship — which column in each table should be matched. Usually this is a primary key from one table and a foreign key from the other.
Returns only rows where there is a match in both tables. Rows from either table that have no match are excluded.
Returns all rows from the left table and matching rows from the right. Unmatched right-side columns become NULL.
Returns all rows from the right table and matching rows from the left. Unmatched left-side columns become NULL.
Returns the Cartesian product — every row from the left table paired with every row from the right. No matching condition required.
FULL OUTER JOIN, but it can be simulated by combining a LEFT JOIN and a RIGHT JOIN with UNION.
When joining tables, always use short aliases — they make your query much easier to write and read:
-- Without aliases: verbose
SELECT customers.name, orders.amount
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
-- With aliases: clean
SELECT c.name, o.amount
FROM customers AS c
INNER JOIN orders AS o ON c.id = o.customer_id;
c for customers, o for orders. For multiple tables starting with the same letter, use c1, c2 or meaningful abbreviations.
ON clause specifies which columns to match — typically a primary key and a foreign key.INNER JOIN, LEFT JOIN, RIGHT JOIN, and CROSS JOIN.