VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
SQL với OracleNối bảng
Bài 9/16
5 phút

LEFT JOIN

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 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ước LEFT 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_id là NULL.
  • Nếu đổi thành JOIN thườ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 JOIN giữ 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 JOIN rồi WHERE 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 JOIN chỉ giữ cặp khớp nhau, LEFT JOIN giữ đủ bảng trái.

Tự kiểm tra

0/3 câu
Câu 1

Muố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ì?

Câu 2

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ì?

Câu 3

Đế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?

INNER JOINSubquery

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt