Skip to content

JOIN: Kết hợp dữ liệu (The Art of Linking)

Dữ liệu trong Database chuẩn hóa (Normalized) thường bị chia nhỏ ra nhiều bảng để tránh dư thừa. JOIN là keo dính để lắp ghép chúng lại với nhau.

Concept: Các loại JOIN phổ biến

Hãy tưởng tượng bạn có 2 tập hợp:

  • A (Mouse): Các con chuột Mickey, Jerry.
  • B (Cat): Các con mèo Tom, Doremon.

Chúng ta sẽ dùng biểu đồ Venn (ASCII Art) để hình dung.

      A (Users)           B (Orders)
   ┌─────────────┐     ┌─────────────┐
   │             │     │             │
   │  User A     │     │   Order 1   │
   │  User B  ───────▶ │   Order 2   │
   │             │     │             │
   └─────────────┘     └─────────────┘

1. INNER JOIN (Giao nhau)

Chỉ lấy những dòng có mặt ở CẢ HAI bảng. Nếu User A không có đơn hàng nào -> User A biến mất khỏi kết quả.

2. LEFT JOIN (Lấy bảng trái làm chuẩn) -> Phổ biến nhất

Lấy TẤT CẢ dòng từ bảng bên TRÁI (A), và các dòng khớp từ bảng PHẢI (B). Nếu User A không có đơn hàng -> Vẫn hiện User A, nhưng thông tin đơn hàng là NULL.

3. RIGHT JOIN (Lấy bảng phải làm chuẩn)

Ngược lại với LEFT JOIN. Ít dùng trong thực tế vì logic suy nghĩ của con người thường là từ Trái sang Phải.

4. FULL OUTER JOIN

Lấy tất cả từ cả A và B. Có thì ghép, không có thì để NULL.

Cú pháp (Syntax)

sql
SELECT users.name, orders.id as order_id
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

Ví dụ thực tế (Real-world Example)

Bạn muốn báo cáo danh sách khách hàng và số tiền họ đã chi tiêu. Phải dùng LEFT JOIN để không bị mất những khách hàng chưa mua gì (để team Marketing còn chăm sóc).

sql
SELECT 
    u.full_name,
    COALESCE(SUM(o.total_amount), 0) as total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.full_name;

💡 HPN Pro Tip: Thứ tự JOIN ảnh hưởng Performance

Mặc dù Query Optimizer hiện đại rất thông minh, nhưng nguyên tắc vàng là: "Table nhỏ trước, Table lớn sau" hoặc "Lọc trước, JOIN sau".

Đừng JOIN cả bảng orders (10 triệu dòng) với users. Hãy lọc orders của ngày hôm nay trước, rồi mới JOIN với users.

⚠️ Common Mistake

Sai lầm chết người: Dùng WHERE trên bảng bên phải khi đang LEFT JOIN.

Sai:

sql
-- Mục tiêu: Lấy tất cả user, nếu có đơn hàng status='completed' thì hiện, không thì thôi.
SELECT * FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.status = 'completed'; -- CÂU NÀY BIẾN LEFT JOIN THÀNH INNER JOIN!

Tại sao? Vì dòng nào có ordersNULL (do không khớp) thì o.status cũng là NULL. So sánh NULL = 'completed' trả về False -> Dòng đó bị loại.

Đúng: Chuyển điều kiện vào ON:

sql
SELECT * FROM users u
LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'completed';