DEV Community

Cover image for SQL Joins Explained.
Josephine Mackylah
Josephine Mackylah

Posted on

SQL Joins Explained.

How Sunrise Supermarket connects its tables

Sunrise Supermarket's database isn't one giant table it's four: customers, products, orders, and order_items.

Each one holds its own piece of the story. Customers live in one table, products in another, and every order plus what was actually bought in it is split across orders and order_items. That's good design, but it means the information you actually want ("which customer bought what") is scattered across all four.
Joins are how you bring them back together.

What Are Joins?

A join combines rows from two or more tables based on a column they share, usually a key like customer_id or product_id.
Think of it as matching two lists side by side: the customers list and the orders list both have a customer_id column, so SQL lines them up and shows you both sides at once.

Types of Joins

JOIN Type What It Returns When to Use It
INNER JOIN Only rows that MATCH in BOTH table When you only want rows with data on both sides
LEFT JOIN ALL rows from the LEFT table + matches from the right (NULL if no match) When you want to keep all left rows, even if no match on the right
RIGHT JOIN ALL rows from the RIGHT table + matches from the left (NULL if no match) When you want to keep all right rows, even if no match on the left
SELF JOIN A table joined to itself When comparing rows within the same table

Practical Examples

INNER JOIN =>customers matched with their orders

SELECT c.full_name, o.order_id, o.status
FROM customers c
INNER JOIN orders o
ON c.customer_id = o.customer_id;
Enter fullscreen mode Exit fullscreen mode
full_name order_id status
Grace Wambui 1 Delivered
Kevin Mutiso 2 Delivered
Grace Wambui 3 Delivered

LEFT JOIN => every order, even ones without items yet

SELECT o.order_id, o.status, i.product_id
FROM orders o
LEFT JOIN order_items i
ON o.order_id = i.order_id;

Enter fullscreen mode Exit fullscreen mode
order_id status product_id
1 Delivered 1
1 Delivered 3
2 Delivered 2
3 Delivered NULL

RIGHT JOIN => every customer, even those with no orders yet

SELECT o.order_id, o.status, c.full_name
FROM orders o
RIGHT JOIN customers c
ON o.customer_id = c.customer_id;
Enter fullscreen mode Exit fullscreen mode
order_id status full_name
1 Delivered Grace Wambui
3 Delivered Grace Wambui
2 Delivered Kevin Mutiso
NULL NULL Faith Chebet
NULL NULL Ibrahim Noor

Notice this is the same result you'd get flipping it into a LEFT JOINwith customers listed first which is exactly why RIGHT JOIN is rarely necessary in practice.

SELF JOIN => products that share the same category

SELECT p1.product_name AS product_a, p2.product_name AS product_b, p1.category
FROM products p1
JOIN products p2
ON p1.category = p2.category AND p1.product_id < p2.product_id;
Enter fullscreen mode Exit fullscreen mode
product_a product_b category
Maize Flour 2kg Cooking Oil 1L Groceries

The table is joined to itself p1 and p2 are just two aliases pointing at the same products table. The p1.product_id < p2.product_id condition stops each pair from being counted twice (and a product from pairing with itself).

# Key takeaways.

Joins turn separate, well-organized tables back into one useful picture without duplicating data everywhere just to keep it together.

Start with INNER JOIN for matches, reach for LEFT JOIN when you need everything from one side.

Top comments (0)