DHDataHọc
TheoryLesson 1/85 min read+10 XP

VLOOKUP và JOIN

Bạn sẽ học được

  • Vì sao VLOOKUP và JOIN giải cùng một bài toán ghép dữ liệu.
  • Cách chuyển một công thức VLOOKUP quen thuộc sang JOIN.
  • Khi nào dùng LEFT JOIN thay vì JOIN.
  • Những giới hạn của VLOOKUP mà SQL không có.
  • Cách kiểm tra kết quả ghép không bị nhân dòng.

Khái niệm cốt lõi

VLOOKUP tìm một giá trị theo khóa ở bảng tra cứu rồi trả về một cột bên phải. JOIN ghép hai bảng theo điều kiện khóa và trả về tất cả cột cần dùng. Cùng mục đích, khác cách tiếp cận:

VLOOKUP (Excel)JOIN (SQL)
=VLOOKUP(A2, Khach!A:D, 3, 0)JOIN customers c ON c.id = o.customer_id
Chỉ lấy một cột mỗi công thứcLấy mọi cột của cả hai bảng
Khóa tra cứu phải nằm bên tráiKhông ràng buộc thứ tự cột
Chỉ lấy kết quả khớp đầu tiênLấy mọi kết quả khớp
Bảng tra cứu cùng fileBảng có thể ở database khác

Ví dụ chuyển đổi

Trong Excel, để thêm tên khách vào bảng đơn hàng:

code
=IFERROR(VLOOKUP(B2, Khach!$A:$D, 2, 0), "Không tìm thấy")

Trong SQL, tương đương:

code
SELECT o.id,
       o.order_date,
       o.status,
       c.name AS ten_khach,
       c.city
FROM orders o
JOIN customers c ON c.id = o.customer_id
ORDER BY o.order_date;

Điểm khác quan trọng: VLOOKUP trả một cột; JOIN trả cả name và city trong cùng một truy vấn. Không cần viết thêm công thức cho từng cột.

LEFT JOIN và dòng không khớp

IFERROR(..., "Không tìm thấy") trong Excel tương ứng LEFT JOIN trong SQL: giữ mọi dòng bên trái, kể cả khi không có bản ghi khớp.

code
SELECT o.id,
       o.order_date,
       c.name AS ten_khach
FROM orders o
LEFT JOIN customers c ON c.id = o.customer_id
WHERE c.id IS NULL;

Truy vấn này trả về các đơn không có khách hàng tương ứng — dữ liệu mồ côi. Đây là kiểm tra chất lượng dữ liệu rất hữu ích mà VLOOKUP khó làm gọn: bạn phải lọc toàn bộ cột kết quả tìm #N/A.

Ngược lại, JOIN (inner join) loại các dòng không khớp. Chọn loại nào là quyết định nghiệp vụ:

  • Muốn báo cáo doanh thu theo khách: dùng JOIN nếu mọi đơn phải có khách hợp lệ.
  • Muốn kiểm tra dữ liệu thiếu: dùng LEFT JOIN ... WHERE c.id IS NULL.
  • Muốn giữ mọi đơn dù thiếu thông tin khách: dùng LEFT JOIN.

Giới hạn của VLOOKUP mà JOIN không có

  1. Chỉ tra bên phải. Khóa phải ở cột đầu; muốn tra ngược phải dùng INDEX/MATCH hoặc XLOOKUP.
  2. Chỉ trả một kết quả. Nếu khóa xuất hiện nhiều lần, VLOOKUP lấy dòng đầu tiên — âm thầm bỏ các dòng còn lại. JOIN trả đủ, và bạn thấy ngay số dòng tăng.
  3. So khớp kiểu dữ liệu. "001" và 1 có thể không khớp nhau trong Excel. Trong SQL, kiểu cột được định nghĩa rõ nhưng vẫn có thể lỗi nếu so chuỗi với số.
  4. Không ghép nhiều điều kiện. JOIN cho phép ON a.id = b.id AND a.ngay = b.ngay.
  5. Không tổng hợp. VLOOKUP lấy giá trị; muốn tổng theo khóa phải dùng SUMIF hoặc PivotTable. SQL dùng GROUP BY.

Kiểm tra ghép không nhân dòng

Nếu bảng tra cứu có khóa trùng, JOIN sẽ nhân dòng và làm sai mọi tổng. Kiểm tra trước:

code
-- Khóa trong bảng tra cứu phải duy nhất
SELECT id, COUNT(*) AS so_lan
FROM customers
GROUP BY id
HAVING COUNT(*) > 1;

Kết quả rỗng nghĩa là khóa duy nhất. Nếu có dòng, phải quyết định giữ bản ghi nào trước khi JOIN — đây chính là lý do VLOOKUP "che" lỗi còn JOIN thì phơi ra.

Sau khi JOIN, so số dòng:

code
SELECT COUNT(*) AS sau_join,
       COUNT(DISTINCT o.id) AS so_don
FROM orders o
JOIN customers c ON c.id = o.customer_id;

Hai số phải bằng nhau nếu mỗi đơn có đúng một khách. Chênh lệch nghĩa là bảng khách có khóa trùng.

Ghép nhiều bảng

Excel thường cần nhiều cột VLOOKUP chồng nhau. SQL nối tiếp:

code
SELECT o.id,
       o.order_date,
       c.name AS ten_khach,
       p.name AS ten_san_pham,
       oi.quantity,
       oi.unit_price,
       oi.quantity * oi.unit_price AS thanh_tien
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN order_items oi ON oi.order_id = o.id
JOIN products p ON p.id = oi.product_id
WHERE o.status = 'completed';

Lưu ý hạt dữ liệu: kết quả ở hạt dòng sản phẩm trong đơn, nên SUM(thanh_tien) đúng nhưng COUNT(*) không phải số đơn. Dùng COUNT(DISTINCT o.id) khi cần đếm đơn.

Thực hành

  1. Viết công thức VLOOKUP lấy tên khách từ customer_id, rồi viết JOIN tương đương.
  2. Chạy LEFT JOIN ... WHERE c.id IS NULL để tìm đơn mồ côi.
  3. Kiểm tra customers.id có trùng không.
  4. Ghép ba bảng orders, order_items, products và tính thành tiền từng dòng.
  5. So COUNT(*) với COUNT(DISTINCT o.id) trong truy vấn trên.

Lỗi thường gặp

Triệu chứngNguyên nhânCách sửa
Doanh thu tăng bất thườngJOIN bảng có khóa trùngKiểm tra khóa duy nhất trước
Mất đơn không có kháchDùng JOIN thay LEFT JOINDùng LEFT JOIN khi cần giữ
Kết quả thiếu cộtNghĩ JOIN như VLOOKUP một cộtChọn thêm cột trong SELECT
Lỗi so sánh khóaKhác kiểu dữ liệuÉp kiểu hoặc chuẩn hoá khóa
Muốn lấy dòng mới nhấtJOIN lấy mọi dòng khớpDùng DISTINCT ON hoặc window
#N/A ở ExcelKhông có bản ghi khớpTrong SQL là dòng NULL sau LEFT JOIN

Tóm tắt

  • VLOOKUP và JOIN cùng mục đích; JOIN linh hoạt và minh bạch hơn.
  • LEFT JOIN tương ứng IFERROR, giữ dòng không khớp.
  • VLOOKUP che khóa trùng; JOIN phơi ra qua số dòng tăng.
  • Kiểm tra khóa duy nhất và so COUNT(*) với COUNT(DISTINCT ...).
  • JOIN nhiều bảng thay cho nhiều cột VLOOKUP, nhưng phải nhớ hạt dữ liệu.

Use ← → to move between lessons