INNER, OUTER, CROSS and FULL joins — how they differ and when to reach for each.
JOINs are used to combine rows from two or more tables based on a related column. There are several types of JOINs in SQL:
SELECT e.name, d.department_name FROM employees e INNER JOIN departments d ON e.department_id = d.id;
SELECT e.name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.id;
A CROSS JOIN produces the Cartesian product of two tables, meaning it combines each row from the first table with every row from the second table.
-- Create sample tables
CREATE TABLE colors (color_name VARCHAR(20));
INSERT INTO colors VALUES ('Red'), ('Green'), ('Blue');
CREATE TABLE sizes (size_name VARCHAR(20));
INSERT INTO sizes VALUES ('Small'), ('Medium'), ('Large');
-- CROSS JOIN to get all combinations
SELECT color_name, size_name
FROM colors
CROSS JOIN sizes;
FULL OUTER JOIN returns all rows from both tables, matching them where possible and filling with NULLs where there's no match.
-- Sample data
CREATE TABLE customers (id INT, name VARCHAR(50));
INSERT INTO customers VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');
CREATE TABLE orders (id INT, customer_id INT, amount DECIMAL);
INSERT INTO orders VALUES (101, 1, 100), (102, 2, 200), (103, 4, 300);
-- FULL OUTER JOIN
SELECT
c.name as customer_name,
o.id as order_id,
o.amount
FROM customers c
FULL OUTER JOIN orders o ON c.id = o.customer_id;
-- Using UNION of LEFT and RIGHT JOIN SELECT c.name, o.id, o.amount FROM customers c LEFT JOIN orders o ON c.id = o.customer_id UNION SELECT c.name, o.id, o.amount FROM customers c RIGHT JOIN orders o ON c.id = o.customer_id;
INNER JOIN returns only matching rows from both tables, while OUTER JOIN returns all rows from one or both tables with NULLs for non-matching rows.
-- Customers table customer_id | name ----------- | ---------- 1 | Alice 2 | Bob 3 | Charlie -- Orders table order_id | customer_id | amount -------- | ----------- | ------ 101 | 1 | 100 102 | 2 | 200 103 | 4 | 300 -- No matching customer
SELECT c.name, o.order_id, o.amount FROM customers c INNER JOIN orders o ON c.customer_id = o.customer_id; -- Result (2 rows): -- Alice - 101 - 100 -- Bob - 102 - 200
SELECT c.name, o.order_id, o.amount FROM customers c LEFT OUTER JOIN orders o ON c.customer_id = o.customer_id; -- Result (3 rows): -- Alice - 101 - 100 -- Bob - 102 - 200 -- Charlie - NULL - NULL
SELECT c.name, o.order_id, o.amount FROM customers c RIGHT OUTER JOIN orders o ON c.customer_id = o.customer_id; -- Result (3 rows): -- Alice - 101 - 100 -- Bob - 102 - 200 -- NULL - 103 - 300
SELECT c.name, o.order_id, o.amount FROM customers c FULL OUTER JOIN orders o ON c.customer_id = o.customer_id; -- Result (4 rows): -- Alice - 101 - 100 -- Bob - 102 - 200 -- Charlie - NULL - NULL -- NULL - 103 - 300