Trong PostgreSQL, việc kết hợp dữ liệu từ nhiều bảng được thực hiện thông qua các mệnh đề JOIN và toán tử UNION. Mỗi phương pháp phục vụ một mục đích cụ thể: JOIN tập trung vào việc liên kết hàng dựa trên mối quan hệ giữa các cột, còn UNION dùng để nối dọc các kết quả truy vấn có cấu trúc tương thích.
Kết hợp toàn phần (CROSS JOIN)
Kết hợp toàn phần tạo ra tích Descartes giữa hai bảng — nghĩa là mỗi hàng của bảng thứ nhất được ghép với mọi hàng của bảng thứ hai. Nếu bảng products có 50 bản ghi và bảng regions có 8 bản ghi, kết quả sẽ chứa 50 × 8 = 400 hàng — bất kể giá trị nào trong các cột.
Hai cú pháp sau đây cho cùng một kết quả:
-- Cách chuẩn hóa theo tiêu chuẩn SQL
SELECT p.name, r.code
FROM products AS p
CROSS JOIN regions AS r;
-- Cách cũ (tương đương nhưng ít rõ ràng)
SELECT p.name, r.code
FROM products AS p, regions AS r;
Lưu ý: Khi không có điều kiện ON hay WHERE, hệ thống không thể xác định mối liên hệ logic — do đó trả về toàn bộ tổ hợp khả thi. Việc sử dụng CROSS JOIN trên các bảng lớn (ví dụ: 100.000 × 100.000) dẫn đến 10 tỷ bản ghi — gây quá tải nghiêm trọng cho bộ nhớ và CPU. Chỉ nên áp dụng khi cần sinh dữ liệu giả lập hoặc mô phỏng phân phối đầy đủ.
Kết hợp trong (INNER JOIN)
INNER JOIN chỉ giữ lại những cặp hàng thỏa mãn điều kiện nối (thường là khóa ngoại khớp với khóa chính). Các hàng không tìm thấy đối tác trong bảng kia sẽ bị loại bỏ hoàn toàn.
SELECT o.order_id, c.customer_name, o.total_amount
FROM orders AS o
INNER JOIN customers AS c ON o.customer_id = c.id;
Kết hợp ngoài (OUTER JOIN)
Các dạng OUTER JOIN mở rộng INNER JOIN bằng cách bảo toàn hàng từ một hoặc cả hai bảng ngay cả khi không có khớp.
- LEFT JOIN: Giữ toàn bộ hàng từ bảng trái (
orders), điềnNULLcho các cột từ bảng phải (customers) nếu không tìm thấy khách hàng tương ứng. - RIGHT JOIN: Ngược lại — bảo toàn tất cả hàng từ bảng phải, điền
NULLcho cột bảng trái khi thiếu khớp. - FULL JOIN: Bảo toàn toàn bộ hàng từ cả hai bảng. Hàng không khớp ở phía nào sẽ có giá trị
NULLcho cột bên kia.
-- Ví dụ FULL JOIN: liệt kê cả đơn hàng chưa có khách và khách chưa đặt hàng
SELECT o.order_id, c.name, o.status
FROM orders AS o
FULL JOIN customers AS c ON o.customer_id = c.id;
Gộp kết quả truy vấn (UNION)
Toán tử UNION nối chồng hai hoặc nhiều câu lệnh SELECT thành một tập kết quả duy nhất. Yêu cầu bắt buộc:
- Số cột trong mỗi
SELECTphải bằng nhau. - Thứ tự và kiểu dữ liệu tương ứng của các cột phải tương thích (ví dụ:
TEXTvớiTEXT,INTEGERvớiBIGINT).
-- Lấy danh sách tên từ hai bảng khác nhau, loại bỏ trùng lặp
SELECT name FROM active_users
UNION
SELECT name FROM archived_users;
-- Giữ lại tất cả bản ghi, kể cả trùng lặp
SELECT name FROM active_users
UNION ALL
SELECT name FROM archived_users;
Khác biệt then chốt: UNION tự động loại bỏ dòng trùng nhờ thao tác DISTINCT nội bộ, trong khi UNION ALL bỏ qua bước này — giúp tăng hiệu năng đáng kể khi dữ liệu đã đảm bảo không trùng hoặc khi yêu cầu giữ nguyên bản sao.