LEFT JOIN
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Phòng marketing muốn gửi mã giảm giá cho những khách chưa từng mua hàng.
INNER JOIN chỉ giữ khách có đơn, nên chính những khách cần tìm lại bị loại.
LEFT JOIN giữ lại cả những khách không có đơn nào.
Khái niệm
🫲 LEFT JOIN: giữ mọi dòng của bảng bên trái, dòng không khớp với bảng bên phải thì các cột của bảng phải là NULL.
Ví dụ
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
ORDER BY c.customer_id, o.order_id;- Bảng bên trái là
customers, đứng trướcLEFT JOIN. - An có hai đơn nên hiện hai dòng. Bình và Chi mỗi người một dòng.
- Dũng không có đơn nào nhưng vẫn có một dòng, với
order_idlà NULL. - Nếu đổi thành
JOINthường thì dòng của Dũng biến mất.
Thử ngay
Tìm những khách chưa từng đặt hàng:
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;Đoán trước khi chạy: ai nằm trong danh sách?
Xem kết quả
| NAME |
|---|
| Dũng |
LEFT JOIN giữ Dũng lại với order_id là NULL. WHERE o.order_id IS NULL
lọc đúng những khách không khớp với đơn nào.
Lỗi hay gặp
Dùng INNER JOIN khi cần cả dòng không khớp. Câu dưới không bao giờ tìm
được khách chưa mua hàng, vì JOIN đã loại họ từ trước.
-- SAI — Dũng bị loại ngay ở bước JOIN
SELECT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;-- ĐÚNG — LEFT JOIN giữ Dũng lại để WHERE tìm ra
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;Lọc bảng bên phải ở WHERE. Điều kiện o.status = 'PAID' loại mọi dòng
không phải PAID, kể cả dòng của khách không có đơn (ở đó o.status là
NULL), nên LEFT JOIN hoạt động như JOIN.
Điều kiện cho bảng bên phải đặt trong ON.
-- SAI — mất Chi và Dũng
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.status = 'PAID';-- ĐÚNG — mọi khách, kèm đơn đã thanh toán nếu có
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
AND o.status = 'PAID';Tóm tắt
LEFT JOINgiữ mọi dòng bảng bên trái, dòng không khớp thì cột bảng phải là NULL.- Tìm dòng "không có":
LEFT JOINrồiWHERE cột_bên_phải IS NULL. - Điều kiện lọc bảng bên phải đặt trong
ON, không đặt ởWHERE. INNER JOINchỉ giữ cặp khớp nhau,LEFT JOINgiữ đủ bảng trái.
Tự kiểm tra
0/3 câuMuốn liệt kê mọi sản phẩm kèm số lượng đã bán, kể cả sản phẩm chưa bán được lần nào. Nên dùng gì?
customers LEFT JOIN orders, khách X không có đơn nào. Cột o.order_id trên dòng của X là gì?
Đếm số đơn của mỗi khách, khách chưa có đơn thì hiện 0. Hàm nào đúng sau LEFT JOIN và GROUP BY c.name?