INNER JOIN chỉ lấy rows có match cả hai bảng; LEFT JOIN lấy tất cả rows bên trái kể cả không có match; WHERE trên cột right table biến LEFT JOIN thành INNER JOIN — đặt filter trong ON clause để tránh.
- INNER JOIN = phần giao (chỉ rows có match cả 2 bảng).
- Visualize bằng Venn diagrams: INNER JOIN = phần giao (chỉ rows có match cả 2 bảng); LEFT JOIN = toàn bộ vòng trái + phần giao (right side NULL nếu không match); RIGHT JOIN = ngược lại (hiếm dùng, viết lại thành LEFT JOIN cho dễ đọc); FULL OUTER JOIN = cả 2 vòng (NULL ở bên không có match); CROSS JOIN = Cartesian product M×N rows (nguy hiểm với bảng lớn).
- Use case thực tế: INNER JOIN khi chỉ muốn users CÓ orders; LEFT JOIN khi muốn TẤT CẢ users kể cả không có orders (NULL check để tìm users chưa mua:
WHERE o.id IS NULL). - Performance: JOIN trên indexed foreign keys rất nhanh; JOIN trên non-indexed columns → Seq Scan + Hash Join chậm.
- Interview trap:
SELECT * FROM A LEFT JOIN B ON A.id = B.a_id WHERE B.col = 'x'— WHERE filter trên B column biến LEFT JOIN thành INNER JOIN vì NULL rows bị lọc ra; phải dùngAND B.col = 'x'trong ON clause để giữ NULL rows. - Self JOIN:
SELECT e.name, m.name as manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id— join bảng với chính nó để resolve hierarchical data.