Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 19 — Data thinking cho Designer: làm quen với SQL

Từ Designer sang BA: Lộ Trình Chuyển Đổi Bài 19/60

Mở đầu — vì sao bài này quan trọng

Là một Designer, bạn đã quen với việc ra quyết định dựa trên trực giác thị giác, phản hồi từ user test, và cảm quan về cái đẹp. Nhưng khi bước vào vai trò BA, bạn sẽ nhận ra một sự thật khắc nghiệt: sếp và dev không quan tâm bạn "cảm thấy" thế nào, họ quan tâm dữ liệu nói gì.

Đây chính là lúc SQL bước vào cuộc chơi. SQL (Structured Query Language) là ngôn ngữ để bạn "hỏi" cơ sở dữ liệu và nhận về câu trả lời bằng con số thật. Với một BA, biết SQL không phải để trở thành lập trình viên — mà để bạn tự mình xác minh yêu cầu, không phải ngồi đoán mò hay chờ đợi người khác.

Hãy hình dung tình huống này. Trong một buổi họp, một Product Manager nói: "Người dùng ở tab Lịch sử đơn hàng rất ít, nên bỏ tính năng đó đi." Là Designer, bạn sẽ tranh luận bằng cảm nhận về trải nghiệm. Là BA giỏi, bạn mở laptop, chạy một câu query 30 giây, và nói: "Thực tế 42% người dùng active trong 30 ngày qua đã vào tab này ít nhất một lần, trong đó nhóm khách VIP dùng nhiều nhất. Chúng ta không nên bỏ." Sự khác biệt về sức nặng trong phòng họp là một trời một vực.

Điểm mạnh của Designer khi học SQL là bạn vốn có tư duy về cấu trúc và quan hệ — bạn đã từng làm việc với component, với design system, với việc dữ liệu chảy qua các màn hình. SQL chỉ là cách diễn đạt tư duy đó bằng ngôn ngữ của database. Bài học này sẽ giúp bạn chuyển từ "data thinking" mơ hồ sang khả năng thực sự truy vấn dữ liệu.

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

Database và bảng (table) — hãy nghĩ như một Excel khổng lồ, có kỷ luật

Nếu bạn từng dùng Excel hay Google Sheets, bạn đã hiểu 80% khái niệm database. Một table giống một sheet: có các cột (column) là các thuộc tính, và các hàng (row) là từng bản ghi. Ví dụ bảng users có cột id, name, email, created_at, và mỗi hàng là một người dùng cụ thể.

Khác biệt lớn nhất so với Excel: database có schema — tức là cấu trúc được định nghĩa nghiêm ngặt. Cột created_at luôn là ngày giờ, cột id luôn là số nguyên và không trùng lặp. Đây là điều một Designer cần nắm: dữ liệu thật có kỷ luật, và khi bạn viết requirement, bạn phải tôn trọng cấu trúc đó.

Câu lệnh SELECT — trái tim của mọi truy vấn

99% công việc SQL của một BA nằm ở việc đọc dữ liệu, không phải sửa. Và câu lệnh để đọc là SELECT. Cấu trúc cơ bản:

SELECT cột_bạn_muốn
FROM tên_bảng
WHERE điều_kiện_lọc;

Ví dụ, để lấy tên và email của tất cả người dùng đăng ký sau ngày 1/1/2026:

SELECT name, email
FROM users
WHERE created_at >= '2026-01-01';

Đọc từ trên xuống: "Lấy (SELECT) cột name và email, từ (FROM) bảng users, với điều kiện (WHERE) ngày tạo từ 1/1/2026 trở đi." Đơn giản như một câu tiếng Anh.

Các mảnh ghép bạn sẽ dùng hằng ngày

  • WHERE — lọc theo điều kiện. Ví dụ WHERE status = 'active' hay WHERE age > 25.
  • ORDER BY — sắp xếp. ORDER BY created_at DESC là sắp mới nhất lên đầu.
  • LIMIT — giới hạn số hàng trả về. LIMIT 10 để xem 10 dòng đầu, tránh làm treo máy khi bảng có triệu bản ghi.
  • COUNT() — đếm số lượng. SELECT COUNT(*) FROM orders cho biết có bao nhiêu đơn hàng.
  • GROUP BY — nhóm dữ liệu để tổng hợp. Đây là công cụ mạnh nhất của BA, ta sẽ nói kỹ bên dưới.

GROUP BY — nơi Designer trở thành nhà phân tích

GROUP BY giúp bạn trả lời câu hỏi dạng "mỗi nhóm có bao nhiêu?". Ví dụ, muốn biết mỗi trạng thái đơn hàng có bao nhiêu đơn:

SELECT status, COUNT(*) AS so_luong
FROM orders
GROUP BY status;

Kết quả trả về kiểu: pending: 340, completed: 1250, cancelled: 89. Chỉ một câu query, bạn đã có bức tranh toàn cảnh mà trước đây phải xin từ team data.

JOIN — khi dữ liệu nằm ở nhiều bảng

Dữ liệu thực tế hiếm khi nằm gọn trong một bảng. Bảng orders thường chỉ lưu user_id chứ không lưu tên khách. Muốn biết tên khách của mỗi đơn, bạn phải JOIN hai bảng lại:

SELECT orders.id, users.name, orders.total
FROM orders
JOIN users ON orders.user_id = users.id;

Hãy nghĩ về JOIN như việc bạn nối hai component qua một prop chung. user_id trong bảng orders "trỏ" đến id trong bảng users — giống như một liên kết trong Figma. Ban đầu JOIN trông đáng sợ, nhưng đây chính là kỹ năng phân biệt một BA biết SQL thật sự với người chỉ copy query trên mạng.

Tình huống thực tế

Tình huống 1: Sàn thương mại điện tử — cứu một tính năng khỏi bị "chém"

Linh là một UX Designer vừa chuyển sang BA tại một sàn TMĐT tầm trung ở TP.HCM (khoảng 500.000 người dùng active hằng tháng). Trong buổi họp roadmap quý, Product Owner đề xuất bỏ tính năng "Danh sách yêu thích" (wishlist) vì "trông có vẻ ít người dùng".

Nếu là 6 tháng trước, Linh sẽ tranh luận bằng nguyên tắc UX. Nhưng lần này cô mở database và chạy:

SELECT COUNT(DISTINCT user_id) AS nguoi_dung_wishlist
FROM wishlist_items
WHERE created_at >= '2026-01-01';

Kết quả: 68.000 người dùng đã thêm sản phẩm vào wishlist trong 6 tháng. Cô chạy tiếp một query JOIN để xem trong nhóm đó, bao nhiêu người sau này thực sự mua món hàng họ đã "thích":

SELECT COUNT(DISTINCT w.user_id) AS da_mua
FROM wishlist_items w
JOIN orders o ON w.user_id = o.user_id AND w.product_id = o.product_id;

Con số: 19.000 người — tức khoảng 28% wishlist dẫn tới đơn hàng thật. Wishlist không phải tính năng chết, mà là một phễu chuyển đổi âm thầm.

Bài học: Dữ liệu đã biến Linh từ người "cãi nhau bằng cảm tính" thành người "chốt quyết định bằng bằng chứng". Tính năng được giữ lại, và Linh được PO tin tưởng giao thêm việc phân tích.

Tình huống 2: Fintech — xác minh requirement trước khi dev code

Tại một công ty ví điện tử ở Hà Nội, một BA mới yêu cầu dev xây màn hình "Giao dịch thất bại gần đây" với giả định người dùng thường có nhiều giao dịch lỗi cần xem lại. Dev ước tính mất 2 tuần để làm.

Trước khi bút phê, BA trưởng nhóm bảo cô kiểm tra dữ liệu thật:

SELECT
  CASE WHEN failed_count = 0 THEN '0 lỗi'
       WHEN failed_count BETWEEN 1 AND 3 THEN '1-3 lỗi'
       ELSE 'trên 3 lỗi' END AS nhom,
  COUNT(*) AS so_nguoi
FROM (
  SELECT user_id, COUNT(*) AS failed_count
  FROM transactions
  WHERE status = 'failed' AND created_at >= '2026-01-01'
  GROUP BY user_id
) t
GROUP BY nhom;

Kết quả gây sốc: 94% người dùng có 0 giao dịch thất bại trong 6 tháng. Chỉ khoảng 1,2% có trên 3 lỗi. Màn hình đắt đỏ kia sẽ phục vụ gần như không ai.

Bài học: SQL đã tiết kiệm cho công ty 2 tuần công sức dev. Một BA biết truy vấn dữ liệu trước khi viết requirement sẽ tránh được việc xây tính năng không ai cần — cạm bẫy kinh điển mà Designer hay mắc vì thói quen "thiết kế cho trường hợp lý tưởng".

Tình huống 3: Ứng dụng học trực tuyến — trả lời PM trong 5 phút

Tại một startup edtech ở Đông Nam Á, PM nhắn trong nhóm chat lúc 4 giờ chiều: "Có ai biết khóa học nào có tỷ lệ hoàn thành thấp nhất tháng này không? Cần cho báo cáo 5 giờ chiều." Bình thường câu này sẽ chờ analyst tới sáng hôm sau. BA từ nền Design gõ nhanh:

SELECT c.title,
       ROUND(COUNT(CASE WHEN e.completed THEN 1 END)  100.0 / COUNT(), 1) AS ty_le_hoan_thanh
FROM enrollments e
JOIN courses c ON e.course_id = c.id
WHERE e.enrolled_at >= '2026-06-01'
GROUP BY c.title
ORDER BY ty_le_hoan_thanh ASC
LIMIT 5;

5 phút sau, cô dán bảng kết quả vào chat. PM kịp báo cáo, và từ đó cô trở thành "người-đi-hỏi-đầu-tiên" của cả team.

Bài học: Giá trị lớn nhất của SQL với BA không phải là câu query phức tạp, mà là tốc độ trả lời. Bạn giải quyết 80% câu hỏi vặt mà không cần làm phiền team data — biến mình thành mắt xích không thể thiếu.

Hướng dẫn từng bước

Bước 1 — Xin quyền truy cập read-only. Đề nghị team kỹ thuật cấp cho bạn một tài khoản database chỉ đọc (read-only). Điều này quan trọng: bạn không thể vô tình xóa hay sửa dữ liệu, nên team sẽ yên tâm cấp quyền. Nhấn mạnh "read-only" khi xin sẽ tăng tỷ lệ được đồng ý.

Bước 2 — Cài một công cụ query thân thiện. Với người mới, hãy dùng DBeaver (miễn phí) hoặc TablePlus (giao diện đẹp, có bản dùng thử). Chúng có giao diện trực quan để duyệt bảng bằng chuột trước khi viết query — rất hợp với tư duy thị giác của Designer.

Bước 3 — Khám phá schema trước khi viết. Trước khi query, hãy duyệt qua danh sách các bảng và cột. Hãy vẽ ra (mental model hoặc trên giấy) các bảng chính và cách chúng liên kết qua các cột *_id. Đây chính là kỹ năng "mapping" mà bạn đã giỏi từ thời làm user flow.

Bước 4 — Bắt đầu bằng SELECT nhỏ, có LIMIT. Luôn thêm LIMIT 10 khi mới khám phá một bảng lạ, để xem dữ liệu trông thế nào mà không làm chậm hệ thống:

SELECT * FROM orders LIMIT 10;

Bước 5 — Thêm điều kiện, rồi tổng hợp. Từ câu SELECT cơ bản, thêm dần WHERE, rồi GROUP BY, rồi JOIN. Xây query như xây wireframe: từ khung xám đến chi tiết.

Bước 6 — Đối chiếu với người biết. Khi có kết quả quan trọng, hãy nhờ một dev hoặc analyst review query của bạn một lần. Sau vài lần, bạn sẽ tự tin đứng vững.

Lỗi thường gặp & mẹo

Quên WHERE khi đếm. Câu SELECT COUNT(*) FROM orders đếm tất cả đơn hàng từ khai thiên lập địa, bao gồm cả đơn test và đơn đã hủy. Luôn hỏi: "Tôi có cần lọc theo thời gian, theo trạng thái không?" Con số không có bối cảnh là con số nguy hiểm.

Nhầm giữa COUNT(\) và COUNT(DISTINCT). COUNT() đếm số hàng; COUNT(DISTINCT user_id) đếm số người dùng riêng biệt. Một người mua 5 đơn sẽ được đếm 5 lần ở cái đầu, 1 lần ở cái sau. Nhầm lẫn này khiến bạn báo cáo "50.000 khách hàng" trong khi thực tế chỉ có 12.000.

Cẩn thận với NULL. Trong database, ô trống mang giá trị NULL (không xác định), không phải 0 hay chuỗi rỗng. Điều kiện WHERE phone != '' sẽ bỏ sót các hàng có phone là NULL. Muốn bắt ô trống thật sự, dùng WHERE phone IS NULL.

Chạy nhầm lệnh sửa/xóa. Đây là lý do bước 1 quan trọng. Với tài khoản read-only, dù bạn có gõ nhầm DELETE thì hệ thống cũng từ chối. Đừng bao giờ tập SQL trên tài khoản có quyền ghi vào database production.

Mẹo vàng: Trước khi trình bày một con số cho sếp, hãy tự hỏi "con số này có hợp lý không?". Nếu query báo rằng công ty có 900.000 khách hàng nhưng bạn biết app chỉ mới ra mắt 3 tháng, gần như chắc chắn query của bạn đang sai (thường do JOIN bị nhân đôi hàng). Trực giác về độ hợp lý — thứ Designer vốn có — là lớp bảo vệ cuối cùng.

Bài tập thực hành

Hãy tưởng tượng bạn có ba bảng của một app đặt đồ ăn: users (id, name, city, created_at), orders (id, user_id, restaurant_id, total, status, created_at), và restaurants (id, name, city).

  • Viết query đếm tổng số người dùng đăng ký tại Hà Nội.
  • Viết query đếm số đơn hàng có trạng thái completed trong tháng 6/2026.
  • Dùng GROUP BY để liệt kê mỗi thành phố có bao nhiêu người dùng, sắp xếp từ nhiều đến ít.
  • Dùng JOIN để lấy tên nhà hàng và tổng doanh thu (SUM(total)) của mỗi nhà hàng, chỉ tính đơn completed, sắp theo doanh thu giảm dần, lấy top 10.
  • Thử thách BA: Sếp hỏi "Có bao nhiêu người dùng đăng ký nhưng chưa bao giờ đặt đơn nào?". Gợi ý: bạn cần một LEFT JOIN và điều kiện WHERE orders.id IS NULL. Đây chính là dạng câu hỏi thật bạn sẽ gặp mỗi tuần.
Hãy làm ít nhất bốn câu đầu bằng cách viết ra giấy hoặc trên một database mẫu (bạn có thể tạo miễn phí trên trang db-fiddle.com). Đừng chỉ đọc — hãy gõ.

Tóm tắt

SQL không biến bạn thành lập trình viên; nó biến bạn thành một BA có tiếng nói bằng dữ liệu. Với Designer chuyển nghề, đây là bước nhảy từ "tôi nghĩ user muốn thế này" sang "dữ liệu cho thấy user thật sự làm thế này".

Những điểm cần nhớ: SELECT ... FROM ... WHERE là bộ ba nền tảng; GROUP BYCOUNT() giúp bạn tổng hợp; JOIN nối dữ liệu từ nhiều bảng như nối các mảnh flow. Luôn xin tài khoản read-only, luôn thêm LIMIT khi khám phá, và luôn kiểm tra tính hợp lý của con số trước khi trình bày.

Ba tình huống thực tế cho thấy giá trị cốt lõi: xác minh requirement bằng dữ liệu thật thay vì đoán, và trả lời 80% câu hỏi của dev/PM ngay lập tức mà không phải chờ analyst. Chỉ cần thành thạo những câu query trong bài này, bạn đã đi trước phần lớn BA cùng cấp — và tận dụng được đúng thế mạnh tư duy cấu trúc mà nghề Design đã rèn cho bạn. Ở các bài sau về data model và ERD, nền tảng SQL này sẽ càng phát huy sức mạnh.