Building one table from two by matching rows on a shared key — inner keeps matches, outer joins keep the unmatched too, NULL-filled.
A join builds one combined table from two by pairing rows on a shared column — the join key. The join *type* decides what happens to rows that have no match on the other side.
Employee Department
name | dept_id dept_id | dept_name
-------+--------- --------+------------
Alice | 10 10 | Engineering
Bob | 20 20 | Sales
Carol | 30 40 | LegalThe join key is dept_id. Note that Carol's dept 30 has no matching department, and Legal (40) has no matching employee — those are the interesting rows.
Alice-Engineering, Bob-Sales. Carol and Legal vanish.NULL: adds Carol-NULL.NULL: adds NULL-Legal.Carol-NULL and NULL-Legal.SELECT e.name, d.dept_name
FROM Employee e
INNER JOIN Department d ON e.dept_id = d.dept_id;
-- Alice|Engineering, Bob|Sales (2 rows)
-- swap INNER for LEFT / RIGHT / FULL OUTER to keep the unmatched rowsNULL, meaning 'no value'. NULL = NULL is never true, so a later WHERE d.dept_name = 'Legal' silently drops the NULL-filled rows — a classic outer-join trap.A cross join ignores any key and pairs *every* row with *every* row — the Cartesian product. With 3 employees and 3 departments that is 3 × 3 = 9 rows.
SELECT e.name, d.dept_name FROM Employee e CROSS JOIN Department d; -- 9 rowsdept_id. Carol's dept_id (30) matches no department. What appears for Carol in the result?