Combining Tables with JOINs
Our marketplace schema stores related information across several tables. Customers place orders, orders contain products through order items, and products belong to categories and sellers. To answer most real-world questions you must combine these tables. That is exactly what SQL joins do.
Learning Goals
- Understand INNER, LEFT, and (conceptual) RIGHT/FULL joins using marketplace data
- Write join queries that combine customers, orders, products, categories, and sellers
- Use table aliases and fully qualified column names to avoid ambiguity
- Recognize common mistakes when joining multiple tables
INNER JOIN
An INNER JOIN returns only rows where the join condition matches. Use it when you need data that exists on both sides - for example, listing customers who have selected a preferred category.
SELECT c.customer_id,
CONCAT(c.first_name, ' ', c.last_name) AS customer_name,
cat.category_name
FROM customer AS c
INNER JOIN category AS cat ON cat.category_id = c.preferred_category_id
ORDER BY customer_name;
Customers whose preferred_category_id is NULL are excluded because there is no matching category row.
LEFT JOIN
A LEFT JOIN returns every row from the left table and matches from the right table when they exist. This is perfect for finding customers without a stated preference.
SELECT c.customer_id,
CONCAT(c.first_name, ' ', c.last_name) AS customer_name,
cat.category_name
FROM customer AS c
LEFT JOIN category AS cat ON cat.category_id = c.preferred_category_id
ORDER BY customer_name;
Customers without a preferred category show NULL in category_name, making them easy to identify.
RIGHT and FULL JOIN (Conceptual)
MySQL supports RIGHT JOIN but does not implement FULL JOIN, so it is still important to understand both:
- RIGHT JOIN: returns every row from the right table plus matches from the left. You can usually rewrite this as a
LEFT JOINby swapping table order. - FULL JOIN: returns every row from both tables, matching where possible and showing
NULLwhen no match exists. You can emulate this by combining aLEFT JOINand aRIGHT JOINwith aUNION.
Joining More Than Two Tables
Most questions touch several tables. For example, to see which customers ordered which products - and which category each product belongs to - you need multiple joins.
SELECT oi.order_item_id,
CONCAT(c.first_name, ' ', c.last_name) AS customer_name,
p.sku,
p.product_name,
cat.category_name,
o.order_date,
o.status
FROM order_item AS oi
JOIN orders AS o ON o.order_id = oi.order_id
JOIN customer AS c ON c.customer_id = o.customer_id
JOIN product AS p ON p.product_id = oi.product_id
JOIN category AS cat ON cat.category_id = p.category_id
ORDER BY o.order_date DESC, o.order_id;
You can chain as many joins as needed. Just add one join clause per relationship.
Joining with Sellers
Because each product can reference a seller, you can extend the previous example to include store information.
SELECT p.sku,
p.product_name,
cat.category_name,
s.store_name,
CONCAT(s.first_name, ' ', s.last_name) AS seller_contact
FROM product AS p
JOIN category AS cat ON cat.category_id = p.category_id
LEFT JOIN seller AS s ON s.seller_id = p.seller_id
ORDER BY cat.category_name, p.sku;
The LEFT JOIN ensures products still appear even if a seller has not been assigned yet.
Using Table Aliases
Aliases keep join queries readable and help you disambiguate similarly named columns.
SELECT c.customer_id,
c.first_name,
c.last_name,
p.sku,
o.order_date
FROM customer AS c
JOIN orders AS o ON o.customer_id = c.customer_id
JOIN order_item AS oi ON oi.order_id = o.order_id
JOIN product AS p ON p.product_id = oi.product_id
WHERE o.status = 'Delivered';
The alias (AS c, AS o, AS oi, AS p) lets you refer to columns quickly without repeating full table names.
Handling Ambiguous Column Names
When two tables share a column name (for example, both customer and seller have first_name), qualify the column with its alias to avoid errors.
SELECT o.order_id,
o.status AS order_status,
t.status AS transaction_status
FROM orders AS o
JOIN transactions AS t ON t.order_id = o.order_id
ORDER BY o.order_id;
Common Pitfalls
- Missing join condition: Forgetting the
ONclause produces a Cartesian product (every row matched with every other row). - Wrong join type: Using
INNER JOINwhen you really needLEFT JOINdrops unmatched rows. - Ambiguous columns: Always prefix duplicated column names with their table alias.
- Join order confusion: Sketch the relationships (or refer to the ER diagram) before writing complicated join chains.
- Null handling: Be aware of optional foreign keys such as
customer.preferred_category_idandproduct.seller_id.
Summary
- Use
INNER JOINwhen you only care about matching rows. - Use
LEFT JOINto keep unmatched left-side records (great for spotting null foreign keys). - Chain joins to pull together customers, orders, products, categories, and sellers.
- Rely on aliases and qualified column names for clarity and correctness.
Quiz
Show quiz
-
Which join ensures every customer appears, even if they have not set a preferred category?
A)INNER JOIN
B)LEFT JOIN
C)RIGHT JOIN
D)FULL JOIN -
What columns do you join on when connecting
orderstocustomer?
A)order_id = customer_id
B)customer_idin both tables
C)product_idin both tables
D)category_idin both tables -
Why is
productjoined tocategoryin many examples?
A) They share the same primary key
B) Each product belongs to a category viacategory_id
C) Every category has exactly one product
D) To filter out products with NULL seller assignments -
True or False: You can rewrite any
RIGHT JOINas aLEFT JOINby swapping table order.
A) True
B) False
Answers
- B
- B
- B
- A