Skip to content

📝 Blog Buổi 5: SQL JOIN — Ghép puzzle dữ liệu như thế nào?

Uber xử lý hàng tỷ trip records mỗi ngày. Không ai mở Excel để làm việc đó. Họ dùng SQL.

Hook

Hình dung bạn đang đứng trong thư viện quốc gia — hàng triệu cuốn sách, xếp trên hàng nghìn kệ, trải khắp 5 tầng lầu.

Bạn cần tìm một cuốn sách. Không có hệ thống phân loại, bạn sẽ đi bộ qua từng kệ, đọc từng gáy sách, và mất... 3 tuần. Nhưng thư viện có hệ thống chỉ mục (index) — gõ tên sách vào máy tính, nó chỉ ngay: tầng 3, kệ B, hàng 7, vị trí thứ 12. Mất 30 giây.

Database là thư viện đó. SQL là hệ thống chỉ mục. Và bạn — Data Analyst — là người biết cách tra cứu.

Bạn có thể đọc, lọc, ghép, gom nhóm hàng triệu dòng dữ liệu chỉ với vài dòng lệnh. Không cần kéo thả. Không cần copy-paste. Không cần đợi Excel đơ 10 phút vì file quá nặng.

Hôm nay bạn sẽ học ngôn ngữ mạnh nhất mà mọi Data Analyst trên thế giới đều dùng — SQL (Structured Query Language).

🤔 Tại sao SQL quan trọng?

Bạn đã biết Excel. Bạn làm được Pivot Table. Bạn build được dashboard. Vậy tại sao cần SQL?

Vì Excel có trần — 1.048.576 dòng. Nghe nhiều, nhưng một cái database e-commerce trung bình có hàng chục triệu dòng đơn hàng, hàng trăm triệu dòng log hành vi người dùng. File Excel 10 triệu dòng? Không mở nổi. Mở nổi thì không tính nổi. Tính nổi thì mất cả buổi.

SQL thì khác. Bạn viết một câu query, database xử lý hàng tỷ dòng trong vài giây. Đó là lý do Uber, Grab, Shopee, Netflix, và mọi công ty lớn nhỏ đều dùng SQL làm xương sống cho phân tích dữ liệu.

Trên thị trường tuyển dụng Việt Nam năm 2026, 92% JD tuyển Data Analyst yêu cầu SQL. Không phải "biết thì tốt" — mà là bắt buộc. LinkedIn, TopCV, ITviec — bạn search thử đi. SQL xuất hiện trước cả Python, trước cả Power BI.

SQL không phải ngôn ngữ lập trình theo nghĩa truyền thống. Nó giống tiếng Anh hơn bạn nghĩ:

"SELECT tên sản phẩm, doanh thu FROM bảng đơn hàng WHERE khu vực = 'TP.HCM' ORDER BY doanh thu giảm dần"

Đọc lên nghe gần như tiếng người. Đó là lý do SQL tồn tại hơn 50 năm mà vẫn không có đối thủ.

💀 Sai lầm chết người

Tháng 9/2025. Một buổi phỏng vấn vị trí Data Analyst tại công ty fintech ở Quận 1, TP.HCM.

Ứng viên — gọi là Hùng — CV đẹp. 3 năm kinh nghiệm Business Analyst. Dashboard Power BI rất pro. Presentation skill tốt. Vượt qua 2 vòng behavioral interview.

Vòng 3 — technical test. Người phỏng vấn đưa cho Hùng một ERD (Entity Relationship Diagram) gồm 4 bảng: customers, orders, products, order_items. Yêu cầu: "Viết query tìm top 10 khách hàng có tổng giá trị đơn hàng cao nhất trong quý 3/2025."

Hùng nhìn ERD. Im lặng 2 phút. Rồi viết:

sql
SELECT * FROM orders WHERE date = 'Q3 2025'

Người phỏng vấn hỏi: "Vậy tên khách hàng lấy ở đâu? Giá sản phẩm ở bảng nào? Làm sao tính tổng?"

Hùng không trả lời được. Hùng không biết JOIN.

Buổi phỏng vấn kết thúc sau 15 phút. Hùng bị loại — không phải vì kém, mà vì thiếu một kỹ năng nền tảng mà nhà tuyển dụng coi là mặc định phải có.

Sai lầm thứ hai: nhiều người học SQL bằng cách đọc lý thuyết, thuộc cú pháp, nhưng chưa bao giờ query trên dữ liệu thực. Giống như học lái xe bằng cách đọc sách — biết hết lý thuyết nhưng lên xe là chết máy. SQL phải viết, phải chạy, phải thấy kết quả, phải sai rồi sửa — thì mới thành kỹ năng.

Sai lầm thứ ba: dùng SELECT * cho mọi query. Bạn cần tên khách hàng và doanh thu, nhưng lại kéo về toàn bộ 50 cột của bảng. Database phải truyền dữ liệu gấp 10 lần cần thiết. Query chậm. Server quá tải. DBA (Database Administrator) gọi điện mắng. Đây là lỗi kinh điển của DA mới — và hoàn toàn tránh được bằng việc chỉ SELECT đúng cột mình cần.

🧪 Ai đã làm đúng?

Uber — công ty ride-hailing lớn nhất thế giới — xử lý hơn 100 petabyte dữ liệu và hàng tỷ trip records. Mỗi chuyến xe tạo ra hàng chục điểm dữ liệu: vị trí đón, vị trí trả, thời gian, quãng đường, giá cước, đánh giá tài xế, phương thức thanh toán.

Đội Data Analyst của Uber dùng SQL hàng ngày để trả lời những câu hỏi kinh doanh quan trọng: "Khu vực nào có thời gian chờ trung bình cao nhất?", "Giờ nào trong ngày có demand vượt supply?", "Tài xế mới có tỷ lệ hủy chuyến cao hơn tài xế cũ bao nhiêu phần trăm?"

Mỗi câu hỏi đó yêu cầu JOIN nhiều bảng — bảng trips, bảng drivers, bảng cities, bảng payments — rồi GROUP BY để gom nhóm, HAVING để lọc kết quả tổng hợp. Không có SQL, những câu hỏi này sẽ mất hàng tuần để trả lời bằng Excel. Với SQL, mất vài phút.

Gần hơn — Grab.

Grab Việt Nam có hàng triệu chuyến xe mỗi ngày. Đội analytics dùng SQL để phân tích surge pricing: JOIN bảng rides với bảng zones và bảng weather, GROUP BY theo khu vực và khung giờ, tính trung bình thời gian chờ. Kết quả: Grab biết chính xác lúc nào, ở đâu cần tăng giá để cân bằng cung cầu — và lúc nào nên giảm giá để giữ chân người dùng.

Hay Shopee — mỗi đợt flash sale, đội DA query database để biết: sản phẩm nào hết hàng nhanh nhất, seller nào có tỷ lệ hủy đơn cao, khu vực nào có conversion rate thấp bất thường. Tất cả bằng SQL. Tất cả trong thời gian thực.

🎯 Vậy cụ thể là làm gì?

🗄 Relational Database — Thư viện có hệ thống

Relational Database (cơ sở dữ liệu quan hệ) lưu trữ dữ liệu trong các bảng (table), giống như các sheet Excel — nhưng có cấu trúc chặt chẽ hơn nhiều.

Mỗi bảng có:

  • Columns (cột) — các trường dữ liệu: customer_id, name, email, phone.
  • Rows (dòng) — mỗi dòng là một bản ghi: một khách hàng, một đơn hàng, một sản phẩm.
  • Primary Key (PK) — khóa chính — một cột (hoặc tổ hợp cột) duy nhất cho mỗi dòng. Giống số CMND — không ai trùng ai. Ví dụ: customer_id trong bảng customers.
  • Foreign Key (FK) — khóa ngoại — cột liên kết đến Primary Key của bảng khác. Giống như "địa chỉ tham chiếu." Ví dụ: customer_id trong bảng orders trỏ về customer_id trong bảng customers.

ERD (Entity Relationship Diagram) — sơ đồ thể hiện mối quan hệ giữa các bảng. Giống như bản đồ thư viện — cho bạn biết kệ nào nối với kệ nào, sách được phân loại ra sao. Trước khi viết query, luôn đọc ERD trước — nó cho bạn biết cần JOIN bảng nào với bảng nào, qua cột nào.

🔍 SELECT — Đặt câu hỏi cho database

SELECT là câu lệnh cơ bản nhất — bạn đang hỏi database một câu hỏi.

sql
SELECT product_name, revenue
FROM orders
WHERE region = 'TP.HCM'
ORDER BY revenue DESC
LIMIT 10;

Dịch ra tiếng Việt: "Cho tôi xem tên sản phẩm và doanh thu, từ bảng đơn hàng, ở khu vực TP.HCM, sắp xếp theo doanh thu giảm dần, lấy 10 dòng đầu."

Hãy nghĩ mỗi keyword như một thao tác:

  • SELECT = "Tôi muốn xem gì?" → Chọn cột.
  • FROM = "Lấy từ đâu?" → Chọn bảng.
  • WHERE = "Điều kiện gì?" → Lọc dòng. Giống bộ lọc (filter) trong Excel, nhưng mạnh hơn gấp bội — bạn có thể kết hợp AND, OR, BETWEEN, IN, LIKE để tạo điều kiện phức tạp.
  • ORDER BY = "Sắp xếp thế nào?" → ASC (tăng dần) hoặc DESC (giảm dần).
  • LIMIT = "Lấy bao nhiêu dòng?" → Giới hạn kết quả. Top 10, top 100.

NULL — giá trị đặc biệt nghĩa là "không có dữ liệu." Không phải 0. Không phải chuỗi rỗng. Là không biết. Giống như ô trống trong Excel — nhưng nguy hiểm hơn vì NULL + 5 = NULL, không phải 5. Để lọc NULL, dùng IS NULL hoặc IS NOT NULL, không dùng = NULL.

🧩 JOIN — Ghép 2 mảnh puzzle

Đây là phần quan trọng nhất của buổi hôm nay, và cũng là kỹ năng được hỏi nhiều nhất trong phỏng vấn DA.

Quay lại ví dụ thư viện. Bạn có 2 danh sách:

  • Danh sách A: Mã sách → Tên sách, tác giả, thể loại.
  • Danh sách B: Mã sách → Ngày mượn, người mượn, ngày trả.

Để biết "Ai đang mượn cuốn nào?", bạn cần ghép 2 danh sách lại theo mã sách. Đó chính là JOIN.

JOIN = ghép 2 mảnh puzzle lại theo một cột chung.

sql
SELECT c.name, o.order_date, o.total_amount
FROM customers c
INNER JOIN orders o ON c.customer_id = o.customer_id;

Dịch: "Ghép bảng khách hàng với bảng đơn hàng theo customer_id, cho tôi xem tên khách, ngày đặt hàng, và tổng tiền."

4 loại JOIN — mỗi loại cho kết quả khác nhau:

Loại JOINÝ nghĩaVí dụ thực tế
INNER JOINChỉ lấy dòng khớp cả 2 bảngKhách hàng ĐÃ mua hàng
LEFT JOINLấy tất cả bảng trái, khớp thì ghép, không khớp thì NULLTất cả khách hàng, kể cả chưa mua hàng
RIGHT JOINLấy tất cả bảng phải, khớp thì ghép, không khớp thì NULLTất cả đơn hàng, kể cả đơn không có thông tin khách
FULL OUTER JOINLấy tất cả từ cả 2 bảng, không khớp thì NULLToàn bộ dữ liệu, không bỏ sót gì

Nghĩ về puzzle:

  • INNER JOIN — chỉ giữ những mảnh khớp hoàn hảo với nhau. Bỏ mảnh thừa.
  • LEFT JOIN — giữ tất cả mảnh bên trái, mảnh phải nào khớp thì ghép vào, không khớp thì để trống.
  • RIGHT JOIN — ngược lại. Giữ tất cả mảnh bên phải.
  • FULL OUTER JOIN — giữ tất cả mảnh cả 2 bên. Không bỏ gì cả.

Khi nào dùng gì?

LEFT JOIN là loại bạn sẽ dùng nhiều nhất trong thực tế. Tại sao? Vì bạn thường muốn giữ tất cả bản ghi từ bảng chính (khách hàng, sản phẩm) rồi bổ sung thông tin từ bảng phụ (đơn hàng, đánh giá) — kể cả khi một số bản ghi không có thông tin phụ.

📊 GROUP BY + Aggregation — Xếp nhóm rồi tổng hợp

GROUP BY giống như Pivot Table trong Excel — gom dữ liệu theo nhóm rồi tính toán tổng hợp.

sql
SELECT region, COUNT(*) AS total_orders, SUM(revenue) AS total_revenue
FROM orders
GROUP BY region;

Dịch: "Gom đơn hàng theo khu vực, đếm số đơn và tính tổng doanh thu từng khu vực."

Các hàm aggregation phổ biến:

  • COUNT(*) — Đếm số dòng.
  • SUM() — Tổng.
  • AVG() — Trung bình.
  • MIN() / MAX() — Giá trị nhỏ nhất / lớn nhất.

HAVING — Lọc sau khi đã gom nhóm. Khác với WHERE (lọc trước khi gom):

sql
SELECT region, SUM(revenue) AS total_revenue
FROM orders
WHERE order_date >= '2025-01-01'
GROUP BY region
HAVING SUM(revenue) > 1000000000;

Dịch: "Lấy đơn hàng từ 2025 trở đi, gom theo khu vực, chỉ hiện khu vực có tổng doanh thu trên 1 tỷ."

WHERE lọc dòng thô. HAVING lọc kết quả gom nhóm. Nhớ thứ tự: WHERE → GROUP BY → HAVING.

Subquery — query lồng trong query — khi bạn cần kết quả của query này làm đầu vào cho query khác:

sql
SELECT product_name, revenue
FROM products
WHERE revenue > (SELECT AVG(revenue) FROM products);

Dịch: "Cho tôi xem sản phẩm có doanh thu cao hơn doanh thu trung bình." Query bên trong tính trung bình trước, query bên ngoài dùng kết quả đó để lọc.

🏪 Câu chuyện thực tế

Phương, 28 tuổi, Business Analyst tại một công ty bảo hiểm ở Đà Nẵng.

Phương làm BA 3 năm. Công việc chính: thu thập yêu cầu từ stakeholder, viết tài liệu nghiệp vụ, làm wireframe cho team developer. Phương giỏi giao tiếp, giỏi tư duy logic, nhưng mỗi khi cần phân tích dữ liệu — Phương phải nhờ team IT xuất file Excel. Rồi Phương mở Excel, lọc, pivot, làm báo cáo.

Vấn đề? Mỗi lần nhờ IT, mất 2–3 ngày mới có data. Sếp hỏi gấp? "Dạ em đang đợi IT xuất data ạ." Sếp muốn thêm điều kiện lọc? "Dạ em phải gửi lại yêu cầu cho IT ạ." Phương trở thành nút thắt cổ chai — không phải vì kém, mà vì không có quyền tự truy cập dữ liệu.

Tháng 7/2025, Phương quyết định chuyển hướng sang Data Analyst. Lý do đơn giản: "Mình muốn tự lấy data, tự phân tích, không phụ thuộc ai."

Tuần 1–2: Học SQL cơ bản.

Phương đăng ký tài khoản trên một platform luyện SQL trực tuyến. Bắt đầu từ SELECT, WHERE, ORDER BY. Phương thấy SQL giống tiếng Anh — đọc lên gần như hiểu nghĩa. Phương viết query đầu tiên trên database mẫu của một e-commerce:

sql
SELECT customer_name, city, total_spent
FROM customers
WHERE city = 'Da Nang'
ORDER BY total_spent DESC
LIMIT 20;

"Top 20 khách hàng chi tiêu nhiều nhất ở Đà Nẵng." Kết quả ra trong 0.3 giây. Phương cười. "3 ngày đợi IT, giờ 0.3 giây."

Tuần 3: Học JOIN.

Phương đối mặt với bài toán thực tế: database e-commerce mẫu có 5 bảng — customers, orders, order_items, products, categories. Sếp (giả lập) hỏi: "Khách hàng nào mua sản phẩm thuộc danh mục 'Electronics' nhiều nhất?"

Phương phải JOIN 4 bảng:

sql
SELECT c.customer_name, COUNT(*) AS total_purchases
FROM customers c
INNER JOIN orders o ON c.customer_id = o.customer_id
INNER JOIN order_items oi ON o.order_id = oi.order_id
INNER JOIN products p ON oi.product_id = p.product_id
WHERE p.category = 'Electronics'
GROUP BY c.customer_name
ORDER BY total_purchases DESC
LIMIT 10;

Lần đầu Phương viết sai — quên ON clause, database báo lỗi. Lần thứ hai — JOIN nhầm cột, kết quả ra gấp 10 lần dự kiến (cartesian product — lỗi kinh điển khi JOIN sai). Lần thứ ba — chạy đúng.

Phương hiểu: mỗi JOIN là ghép một mảnh puzzle vào. Bắt đầu từ bảng chính (customers), ghép thêm orders (để biết khách đặt đơn nào), ghép thêm order_items (để biết đơn có sản phẩm nào), ghép thêm products (để biết sản phẩm thuộc danh mục nào). Bốn mảnh puzzle, ghép thành bức tranh hoàn chỉnh.

Tuần 4: GROUP BY + HAVING + Subquery.

Phương thử bài toán nâng cao: "Tìm các khu vực có doanh thu trung bình mỗi đơn hàng cao hơn doanh thu trung bình toàn quốc."

sql
SELECT region, AVG(total_amount) AS avg_order_value
FROM orders
GROUP BY region
HAVING AVG(total_amount) > (SELECT AVG(total_amount) FROM orders);

Subquery bên trong tính trung bình toàn quốc. HAVING so sánh trung bình từng khu vực với con số đó. Kết quả: TP.HCM và Hà Nội có AOV cao hơn trung bình, Đà Nẵng thấp hơn một chút — insight này giúp team marketing phân bổ ngân sách hợp lý hơn.

Tháng 10/2025 — Phương nộp đơn vào vị trí Junior Data Analyst tại một startup e-commerce ở Đà Nẵng.

Vòng phỏng vấn technical, Phương được đưa một ERD và 3 câu hỏi SQL. Phương viết được cả 3 — có JOIN, có GROUP BY, có subquery. Người phỏng vấn hỏi: "Tại sao em dùng LEFT JOIN thay vì INNER JOIN ở câu 2?" Phương trả lời: "Vì em muốn giữ cả những khách hàng chưa có đơn hàng nào, để phân tích nhóm khách inactive."

Phương được nhận. Lương 15 triệu — tăng 25% so với vị trí BA cũ. Nhưng quan trọng hơn: Phương không còn phụ thuộc team IT để lấy data nữa. Sáng mở laptop, viết query, 30 giây có kết quả. Sếp hỏi gì, Phương trả lời được ngay trong cuộc họp — không cần "để em về kiểm tra."

Phương nói: "SQL không khó. Khó là ở chỗ dám bắt đầu. Mình từng nghĩ code là thứ của dân IT. Nhưng SQL không phải code — nó là cách bạn nói chuyện với dữ liệu."

💡 Bài học rút ra

🗣 SQL là ngôn ngữ giao tiếp với data. SELECT = hỏi, WHERE = lọc, JOIN = ghép puzzle, GROUP BY = xếp nhóm. Bốn từ khóa đó giải quyết được 80% câu hỏi phân tích trong công việc hàng ngày. Không cần phức tạp — cần đúng.

🧩 JOIN là kỹ năng phân biệt amateur và professional. Dữ liệu thực tế luôn nằm ở nhiều bảng khác nhau. Không biết JOIN = bạn chỉ nhìn được một mảnh puzzle. Biết JOIN = bạn ghép được toàn bộ bức tranh.

📋 Đọc ERD trước khi viết query. Giống như đọc bản đồ trước khi lái xe. ERD cho bạn biết bảng nào liên kết với bảng nào, qua cột nào, quan hệ 1-nhiều hay nhiều-nhiều. Không đọc ERD mà viết query = lái xe không có GPS.

⚠️ WHERE lọc trước, HAVING lọc sau. Đây là lỗi kinh điển khi phỏng vấn. WHERE lọc dòng thô trước khi GROUP BY. HAVING lọc kết quả tổng hợp sau khi GROUP BY. Nhầm thứ tự = kết quả sai mà không biết sai ở đâu.

🏃 Thực hành > Lý thuyết. SQL phải viết — giống như bơi phải xuống nước. Mở một platform luyện SQL, chọn database mẫu, viết query, xem kết quả, sai thì debug. 2 tuần viết mỗi ngày 5 bài = bạn đã tự tin hơn 90% ứng viên DA.

🔑 Tự lấy data = tự do. Khi bạn biết SQL, bạn không còn phải đợi team IT xuất file. Bạn tự hỏi, tự tìm, tự trả lời. Tốc độ phân tích tăng lên gấp 10 lần — và giá trị của bạn trong tổ chức cũng tăng theo.

🤓 Muốn tìm hiểu thêm?

  • 📚 SQLBolt — Học SQL tương tác, từ cơ bản đến nâng cao, hoàn toàn miễn phí. Bắt đầu từ Lesson 1.
  • 📚 Mode Analytics SQL Tutorial — Hướng dẫn SQL theo hướng phân tích dữ liệu, rất phù hợp cho DA.
  • 🎥 freeCodeCamp — SQL Full Course — Video 4 tiếng, từ zero đến hero, hơn 18 triệu lượt xem.
  • 📖 Learning SQL — Alan Beaulieu (O'Reilly) — Cuốn sách kinh điển, viết dễ hiểu, có nhiều ví dụ thực tế.
  • 🏋️ LeetCode Database Problems — Luyện SQL phỏng vấn, từ Easy đến Hard. Làm 50 bài Easy là đủ tự tin.
  • 🇻🇳 DataCamp — Có track SQL cho Data Analyst, bài tập tương tác ngay trên trình duyệt.

🔗 Xem thêm Buổi 5

📘 Nội dung chính🧠 Case Study🏆 Tiêu chuẩn🛠 Workshop🎮 Mini Game