SQL cơ bản cho BA & UAT/Validation
BA không cần viết code nhưng cần đọc được dữ liệu để đưa ra quyết định có căn cứ. SQL là ngôn ngữ phổ thông nhất để truy vấn database — và đây là kỹ năng phân biệt một BA trung bình với một BA giỏi trong môi trường làm việc thực tế.
Tại sao BA cần SQL?
Trong môi trường product thực tế, BA thường gặp các câu hỏi như:
- "Có bao nhiêu học viên đã đăng ký khóa học trong tháng này?"
- "Mentor nào có tỷ lệ đặt lịch cao nhất nhưng chưa có review?"
- "Học viên nào đã thanh toán nhưng chưa hoàn thành bài học đầu tiên?"
SELECT & WHERE: Lọc dữ liệu cơ bản
-- Lấy danh sách học viên đăng ký từ tháng 7/2026
SELECT
u.id,
u.full_name,
u.email,
e.enrolled_at,
c.title AS course_title
FROM users u
JOIN enrollments e ON e.user_id = u.id
JOIN courses c ON c.id = e.course_id
WHERE e.enrolled_at >= '2026-07-01'
AND e.enrolled_at < '2026-08-01'
ORDER BY e.enrolled_at DESC;
Giải thích cho BA:
SELECT— chọn cột nào cần xem (không lấy*tránh lộ dữ liệu nhạy cảm)WHERE— điều kiện lọc (tương đương bộ lọc trong Excel)AND/OR— kết hợp nhiều điều kiệnORDER BY— sắp xếp kết quả
JOIN: Kết hợp nhiều bảng
Dữ liệu thực tế thường nằm ở nhiều bảng khác nhau. JOIN là cách "ghép" chúng lại.
-- Tìm mentor chưa có review nào sau 30 ngày được approve
SELECT
mp.user_id,
u.full_name AS mentor_name,
u.email,
mp.approved_at,
COUNT(mr.id) AS total_reviews
FROM mentor_profiles mp
JOIN users u ON u.id = mp.user_id
LEFT JOIN mentor_reviews mr ON mr.mentor_id = mp.user_id
WHERE mp.approved_at IS NOT NULL
AND mp.approved_at < DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY mp.user_id, u.full_name, u.email, mp.approved_at
HAVING COUNT(mr.id) = 0
ORDER BY mp.approved_at ASC;
Các loại JOIN BA cần biết:
INNER JOIN(hoặc chỉJOIN): chỉ lấy hàng khớp cả hai bảngLEFT JOIN: lấy tất cả hàng từ bảng trái, bảng phải có thể NULL — dùng khi muốn tìm "những gì chưa có" (ví dụ: mentor chưa có review)
GROUP BY & Aggregate Functions: Tổng hợp dữ liệu
-- Doanh thu theo khóa học trong Q3/2026
SELECT
c.title AS course_title,
c.category,
COUNT(DISTINCT e.user_id) AS total_students,
COUNT(DISTINCT CASE WHEN lp.completed_at IS NOT NULL THEN lp.user_id END) AS completed_students,
ROUND(
COUNT(DISTINCT CASE WHEN lp.completed_at IS NOT NULL THEN lp.user_id END) * 100.0
/ NULLIF(COUNT(DISTINCT e.user_id), 0),
1) AS completion_rate_pct
FROM courses c
JOIN enrollments e ON e.course_id = c.id
LEFT JOIN (
SELECT user_id, course_id, MAX(completed_at) AS completed_at
FROM lesson_progress
WHERE is_final_lesson = 1
GROUP BY user_id, course_id
) lp ON lp.course_id = c.id AND lp.user_id = e.user_id
WHERE e.enrolled_at BETWEEN '2026-07-01' AND '2026-09-30'
GROUP BY c.id, c.title, c.category
HAVING COUNT(DISTINCT e.user_id) >= 5
ORDER BY completion_rate_pct DESC;
Aggregate functions hay dùng:
COUNT(*)— đếm số hàngCOUNT(DISTINCT col)— đếm giá trị không trùngSUM(col)— tổngAVG(col)— trung bìnhMAX/MIN(col)— giá trị lớn nhất/nhỏ nhấtHAVING— lọc sau khi GROUP BY (khác WHERE: WHERE lọc trước khi group)
Best Practice cho BA khi dùng SQL
- Luôn dùng LIMIT khi explore:
SELECT * FROM users LIMIT 100— tránh kéo hàng triệu hàng - Đặt alias rõ ràng:
u.full_name AS mentor_namegiúp đọc kết quả dễ hơn - Comment SQL: giải thích business logic phức tạp ngay trong query
- Không UPDATE/DELETE: BA chỉ nên có quyền SELECT — nếu vô tình có quyền cao hơn, tuyệt đối không dùng
- Lưu query vào file: đặt tên rõ
2026-07-mentor-no-reviews.sql
Test Case: Nền tảng của UAT
Test case là tài liệu mô tả chính xác cách kiểm tra một chức năng. Đây là công cụ chính của BA trong giai đoạn UAT (User Acceptance Testing).
Cấu trúc một test case:
| Trường | Mô tả |
|---|---|
| Test Case ID | TC-001 |
| Tên chức năng | Đặt lịch mentor |
| Điều kiện tiên quyết | Học viên đã đăng nhập, mentor có lịch trống |
| Bước thực hiện | 1. Vào trang mentor / 2. Chọn khung giờ / 3. Điền ghi chú / 4. Click Xác nhận |
| Dữ liệu test | Ngày: 2026-08-01 10:00, Ghi chú: "Tư vấn CV" |
| Kết quả mong đợi | Email xác nhận gửi đến học viên trong 2 phút, booking xuất hiện trong lịch mentor |
| Kết quả thực tế | (điền sau khi test) |
| Pass/Fail | (điền sau khi test) |
Validation vs Verification
Đây là hai khái niệm hay bị nhầm lẫn:
- Verification (Kiểm chứng): "Chúng ta có đang BUILD đúng không?" — kiểm tra sản phẩm so với spec/requirement. Ví dụ: form đăng ký có đủ 5 trường như spec không?
- Validation (Xác nhận): "Chúng ta có đang BUILD đúng thứ không?" — kiểm tra sản phẩm có giải quyết được vấn đề của người dùng không. Ví dụ: học viên có thực sự đặt được lịch dễ dàng không?
- Verification = so với tài liệu (spec, AC)
- Validation = so với người dùng thật (usability test, user interview)
Tự luyện
- Truy cập SQL playground (sql.js hoặc DB Fiddle), tạo bảng
users,courses,enrollmentsvới 10 hàng mẫu. Viết 3 query: (a) đếm học viên theo khóa học, (b) tìm học viên chưa hoàn thành khóa học nào, (c) tỷ lệ hoàn thành theo danh mục. - Chọn một tính năng bạn đang dùng hàng ngày (ví dụ: đăng nhập bằng Google). Viết 5 test case bao gồm: happy path, email sai, tài khoản bị khóa, mất kết nối mạng, đăng nhập lần đầu.
- Phân biệt: tính năng "form đăng ký có đủ trường" là verification hay validation? Tại sao?
Học xong bài này rồi?
Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu,
và học hết khóa thì có chứng chỉ.
Lưu tiến độ của tôi