Với mô hình Challenge-based Learning, bạn không chỉ được học Business Domain Theory, mà còn được giải các Challenges Thực Tế, rèn Tư Duy Phân Tích và tạo Portfolio ngay trong các Khóa Học Phân Tích Dữ Liệu Thực Chiến. Inbox mình Tại Đây nếu bạn muốn đăng ký nhé.
Kiến Thức Chuyên Môn: Giải Mã Metric – KPI – OKR
Metric (Chỉ Số)
- Định nghĩa: Số liệu thô, đo lường hành động hoặc trạng thái cụ thể. Metric là “nguyên liệu”.
- Giảm cân: Số bước chân chạy/ngày, Lượng calo nạp vào/bữa, Số giờ ngủ.
- TungMo Growth: Số lần login app, Số giao dịch chuyển tiền (P2P), Thời gian on-screen.
- Metric là những con số biết nói, dùng để theo dõi mọi thứ đang diễn ra.
- Lagging Metric (Chỉ số kết quả)
- Là kết quả của quá khứ. Khi bạn nhìn thấy số này, sự việc đã xảy ra rồi, không thể thay đổi được nữa. Nó dùng để báo cáo (Reporting).
- Giảm cân: Số cân nặng hiện tại (75kg), Số đo vòng eo (80cm). (Leo lên cân mới biết béo hay gầy, lúc đó ăn xong rồi)
- TungMo Growth: Revenue (Doanh thu tháng trước), Churn Rate (Tỷ lệ rời bỏ). (Khách đã bỏ đi rồi mới đếm được)
- Leading Metric (Chỉ số hành động)
- Là chỉ số dự báo. Nó đo lường hành vi đầu vào. Nếu tác động vào số này ngay bây giờ, nó sẽ làm thay đổi Lagging Metric trong tương lai.
- Giảm cân: Số Calo nạp vào hôm nay, Số phút chạy bộ. (Nếu hôm nay chạy nhiều -> tuần sau cân nặng sẽ giảm)
- TungMo Growth: Active Users (Đang online), Feature Adoption (Số người thử tính năng mới), Successful Transactions (Giao dịch thành công).
- Manager thường quan tâm Lagging Metrics, nhưng Product Team phải làm việc hàng ngày với Leading Metrics để tối ưu kết quả cuối cùng.
KPI (Chỉ Số Hiệu Suất Chính)
- Định nghĩa: Metric quan trọng được gắn với một mục tiêu cụ thể để đánh giá hiệu quả. KPI là “thước đo thành công”.
- Giảm cân: Tỷ lệ hoàn thành 10.000 bước/ngày, Cân nặng trung bình tuần này so với tuần trước (giảm 0.5kg?).
- TungMo Growth: Retention Rate D30 (Tỷ lệ user quay lại sau 30 ngày), Conversion Rate (Tỷ lệ user nạp tiền lần đầu).
- Metric được chọn làm trọng tâm và gán target (mục tiêu) thì thành KPI.
- KPI = Metric (What) + Target (How much) + Timeframe (When)
- Một Metric muốn “thăng hạng” lên làm KPI phải thỏa mãn công thức S.M.A.R.T. Nếu thiếu 1 trong các yếu tố, nó chỉ là một Metric vô hồn.
- Specific (Cụ thể): Chọn đúng Metric cốt lõi, không chung chung.
- Không nói “Giảm béo”. Chọn: % Mỡ cơ thể (Body Fat).
- Không nói “Tăng tương tác”. Chọn: Avg Transaction per User (ATPU).
- Measurable (Đo được): Phải có con số chính xác từ hệ thống, không đoán mò.
- Dùng máy đo ra con số 20%.
- Dùng SQL query ra con số 5.2 trans/user.
- Achievable (Khả thi): Mục tiêu phải thực tế, dựa trên dữ liệu lịch sử (Historical Data).
- Giảm 10kg trong 1 ngày là Vô lý. Giảm 0.5kg/tuần là Khả thi.
- Tăng trưởng 500% trong 1 tháng là Hoang đường. Tăng 10% MoM (Month over Month) là Khả thi.
- Relevant (Liên quan): KPI này có đóng góp gì cho mục tiêu to lớn hơn (OKR) không?
- Giảm mỡ thì mới khỏe/đẹp (Đúng mục tiêu). Đếm số lần thở (Không liên quan).
- Tăng giao dịch thì Doanh thu mới tăng (Đúng). Tăng số lượng nhân viên (Không phải KPI sản phẩm).
- Time-bound (Thời hạn): Deadline
- Trước ngày đi biển (30/06).
- Trước khi kết thúc Quý 2 (30/06).
- Specific (Cụ thể): Chọn đúng Metric cốt lõi, không chung chung.
- Khi Sếp giao: “Em ơi, làm sao tăng trưởng user?”. Bạn phải “bẻ” lại ngay thành KPI: “Ý anh là chúng ta muốn đạt 1 triệu MAU (Metric + Target) vào cuối Quý 4 (Time) hay sao ạ?”.
OKR (Mục Tiêu & Kết Quả Then Chốt)
- Định nghĩa: Một framework quản trị mục tiêu tham vọng. Objective (O) là đích đến cảm hứng, Key Results (KR) là các mốc KPI phải đạt để chứng minh đã đến đích.
- Giảm cân: O: “Có body 6 múi để đi biển mùa hè”. KR1: Giảm 5kg mỡ thừa. KR2: Chạy bộ đạt KPI 10km/tuần trong 3 tháng liên tục.
- TungMo Growth: O: “Biến TungMo thành thói quen tài chính mỗi ngày”. KR1: Đạt 10 triệu Monthly Active Users (MAU). KR2: Tăng Retention Rate D30 lên 45%.
- OKR là bức tranh lớn. KPI/Metrics là các mảnh ghép để hoàn thiện bức tranh đó. KPIs là con của KR (Key Results).
- Cấu trúc cây mục tiêu (The Objective Tree):
- Objective (O): Định tính (Qualitative), truyền cảm hứng, trả lời “We go where?”.
- Giảm cân: “Trở thành phiên bản quyến rũ và khỏe mạnh nhất của chính mình vào mùa hè này.”
- TungMo Growth: “Chiếm lĩnh thị phần thanh toán không tiền mặt tại các cửa hàng tiện lợi (CVS).”
- Key Results (KR): Định lượng (Quantitative), đo lường việc hoàn thành O. KR chính là tập hợp các KPI quan trọng nhất.
- Giảm cân: KR1: Giảm % mỡ cơ thể từ 25% xuống 18%. KR2: Chạy được Half-Marathon (21km) dưới 2h30p.
- TungMo Growth: KR1: Đạt 5 triệu giao dịch/tháng tại hệ thống Circle K & GS25. KR2: Tăng tỷ lệ Active User tại điểm bán lên 30%.
- Initiatives (Hành động): Những việc cụ thể cần làm để đẩy con số KR lên.
- Giảm cân: Đăng ký gói tập Gym 1 năm, Áp dụng chế độ ăn Keto, Ngủ trước 11h đêm.
- TungMo Growth: Chạy campaign “Hoàn tiền 50% khi mua nước ngọt”, Fix lỗi quét QR code bị chậm, Tối ưu UI màn hình thanh toán.
- Objective (O): Định tính (Qualitative), truyền cảm hứng, trả lời “We go where?”.
- OKR: Là la bàn chiến lược, tập hợp các KPI lại để đảm bảo cả công ty cùng nhìn về một hướng.
SQL Challenge: OKR Tăng Retention User
Team Growth TungMo phát động chiến dịch Quý 1/2024: “Xây dựng thói quen tài chính”.
Objective: Tăng Retention bền vững bằng việc giúp user kích hoạt được Aha Moment.
Key Results (Target):
- KR1: Tăng D7 Retention từ 5% -> 8% (User có quay lại vào đúng ngày thứ 7?).
- KR2: Tăng tỷ lệ New Users đạt Streak 3+ từ 12% -> 25% (User giao dịch 3 ngày liên tiếp trong 14 ngày đầu).
- KR3: Giảm % User rơi rụng trong 3 ngày đầu từ 60% -> 45% (Tỷ lệ user không có giao dịch nào trong 3 ngày đầu tiên).
Sử dụng SQL để tính toán hiện trạng của cả 3 KR trên cho tập khách hàng mới (Cohort) tháng 01/2024.
- Định nghĩa Streak: Chuỗi ngày liên tiếp có phát sinh giao dịch tài chính
- Gap: Nếu user giao dịch ngày 1, nghỉ ngày 2, giao dịch ngày 3 -> Streak gãy. Max Streak = 1.
- Condition: Chỉ tính các giao dịch có giá trị amount >= 10.000 VND
- Cohort: Chỉ xét User đăng ký mới trong quý 1/2024.
Output mong muốn:
| Cohort Month | Total Users | KR1 D7 Ret (Target 8%) | KR2 Streak5 (Target 25%) | KR3 DropOff D3 (Target 45%) |
|---|---|---|---|---|
| 2024-01 | 10 | 30.00% | 10.00% | 50.00% |
| 2024-02 | 5 | 40.00% | 0.00% | 60.00% |
| 2024-03 | 5 | 60.00% | 40.00% | 20.00% |
- KR3: Giảm Tỷ Lệ Rơi Rụng 3 Ngày Đầu (Target: < 45%)
- Kết quả: 50.00% (T1) -> 60.00% (T2) -> 20.00% (T3)
- Đây là Leading Metric quan trọng nhất ở phễu đầu vào. Nếu người dùng rời đi trong 3 ngày đầu, họ sẽ không bao giờ có cơ hội tạo thói quen (KR2) hay quay lại ở ngày thứ 7 (KR1).
- Tháng 1 & 2: Tỷ lệ rơi rụng vẫn còn rất cao, thậm chí tệ đi trong tháng 2. Điều này cho thấy trải nghiệm onboarding hoặc giá trị ban đầu chưa đủ hấp dẫn để giữ chân người dùng.
- Tháng 3: Có một sự cải thiện đột phá . Tỷ lệ rơi rụng giảm mạnh xuống chỉ còn 20%, tốt hơn rất nhiều so với mục tiêu 45%. Điều này cho thấy team đã tìm ra “công thức” đúng để cải thiện trải nghiệm onboarding, giúp người dùng mới thấy được giá trị ngay lập tức.
- KR2: Tăng Tỷ Lệ Đạt Streak 5+ (Target: > 25%)
- Kết quả: 10.00% (T1) -> 0.00% (T2) -> 40.00% (T3)
- Đây là một Leading Metric cực mạnh, đo lường việc hình thành “thói quen”. Việc một người dùng giao dịch 5 ngày liên tiếp là dấu hiệu họ đã kích hoạt được “Aha Moment” – mục tiêu chính của chiến dịch.
- Tháng 1 & 2: Kết quả rất đáng báo động. Tỷ lệ này không những không tăng mà còn rơi xuống 0% trong tháng 2. Điều này củng cố giả thuyết rằng các hoạt động trong tháng 2 có thể đã sai hướng, không giúp người dùng xây dựng được hành vi lặp lại.
- Tháng 3: Thành công rực rỡ! Tỷ lệ đạt 40%, vượt xa mục tiêu 25%. Điều này cho thấy các cải tiến trong tháng 3 (có thể liên quan đến việc giảm tỷ lệ rơi rụng ở KR3) đã trực tiếp giúp người dùng gắn bó và hình thành thói quen.
- KR1: Tăng D7 Retention (Target: > 8%)
- Kết quả: 30.00% (T1) -> 40.00% (T2) -> 60.00% (T3)
- Đây vừa là Leading Metric cho retention dài hạn, vừa là Lagging Metric (kết quả) của việc người dùng có một trải nghiệm tốt trong tuần đầu tiên.
- Xu hướng: Chỉ số này tăng trưởng đều qua các tháng, cho thấy nỗ lực của team luôn có tác động tích cực đến việc kéo người dùng quay lại.
- Tháng 3: Con số 60% là một kết quả ấn tượng, cho thấy khi người dùng được onboarding tốt (KR3) và bắt đầu hình thành thói quen (KR2), việc họ quay lại vào ngày thứ 7 là một kết quả tất yếu.
/*
CREATE INDEX idx_users_join_date ON users(join_date);
CREATE INDEX idx_transactions_main ON transactions(user_id, is_financial, amount, txn_date);
*/
WITH
cohort_base AS (
SELECT
user_id,
join_date,
-- CONVERT(char(7), ..., 120): Hàm này cắt chuỗi ngày tháng, chỉ lấy YYYY-MM. Đây là cách chuẩn để tạo Cohort Month trong SQL Server.
-- CONVERT là hàm nội tại (native T-SQL), tốc độ nhanh gấp 10-20 lần khi chạy trên hàng triệu dòng.
CONVERT(char(7), join_date, 120) AS cohort_month
FROM users
WHERE join_date >= '2024-01-01'
),
-- valid_txns: lọc ngay từ đầu. Những giao dịch (non-financial, <10k) bị loại bỏ ngay lập tức để làm nhẹ gánh nặng cho các bước sau.
valid_txns AS (
SELECT
t.user_id,
t.txn_date
FROM transactions t
-- JOIN cohort_base (Kỹ thuật lọc ngược)
-- Thay vì quét cả bảng transactions (gồm cả user cũ năm 2020), JOIN ngược lại với cohort_base (chỉ chứa user mới Q1/2024).
-- Tự động loại bỏ giao dịch của những user không thuộc phạm vi
JOIN cohort_base c ON t.user_id = c.user_id
WHERE t.is_financial = 1 AND t.amount >= 10000
-- Nâng cao Index
-- Bảng users: 1 triệu dòng (nhưng Cohort tháng 1/2024 chỉ có 10.000 user).
-- Bảng transactions: 1 tỷ dòng (lịch sử 5 năm).
-- Cách 1: Dùng JOIN (như trên)
-- Cơ chế: SQL Server sẽ cầm danh sách 10.000 user_id từ bảng cohort_base (đã lọc nhỏ gọn). Sau đó, nó dùng Index của bảng transactions để "gõ cửa" tìm đúng giao dịch của 10.000 người này.
-- Hành động: Index Seek (Tìm đích danh) -> Chi phí: Rất thấp. Chỉ lục lọi những chỗ cần thiết.
-- Cách 2: Dùng WHERE trực tiếp trên bảng Transaction
-- Vấn đề: Bảng transactions thường được Index theo txn_date hoặc user_id.
-- Nếu lọc theo txn_date >= '2024-01-01': Nó vẫn phải quét toàn bộ giao dịch từ ngày đó đến nay (có thể là cả triệu user cũ cũng giao dịch trong năm 2024). Sau đó mới check xem user đó có phải là user mới không. -> Dư thừa lớn.
-- Nếu lọc theo user_id IN (...): Với danh sách ID nhỏ thì nhanh. Nhưng nếu Cohort lên đến 50.000 user, câu lệnh IN (...) sẽ trở nên cực kỳ nặng nề hoặc khiến SQL Server từ bỏ Index Seek mà chuyển sang Index Scan (Quét toàn bộ bảng).
-- Trong thực tế vận hành, dữ liệu thay đổi liên tục.
-- Tình huống: Một user cũ (đăng ký năm 2020) bỗng nhiên giao dịch lại vào tháng 1/2024.
-- Nếu dùng WHERE t.txn_date >= '2024-01-01': Giao dịch của ông user cũ này sẽ lọt vào tập dữ liệu tính toán. Bạn phải tốn thêm một bước WHERE nữa để loại ổng ra.
-- Nếu dùng JOIN cohort_base: Bảng cohort_base đóng vai trò như một "Danh sách VIP". Chỉ những ai có tên trong danh sách này (User mới T1/2024) thì giao dịch của họ mới được phép đi qua cánh cổng JOIN. Những người khác tự động bị chặn đứng.
),
user_flags AS (
SELECT
c.user_id,
c.cohort_month,
-- Tại sao dùng MAX()? Một user có thể giao dịch 10 lần trong 3 ngày đầu
-- -> Sinh ra 10 dòng. Nhưng ta chỉ cần biết CÓ hay KHÔNG (1 hoặc 0). MAX sẽ lấy số 1 nếu có bất kỳ giao dịch nào, và gom 10 dòng đó về 1 dòng duy nhất cho mỗi user.
-- BETWEEN c.join_date AND DATEADD(day, 2) -> Ngày đăng ký (D0) + 2 ngày tiếp theo (D1, D2) = Tổng 3 ngày -> Cửa sổ 3 ngày đầu tiên
MAX(CASE WHEN vt.txn_date BETWEEN c.join_date AND DATEADD(day, 2, c.join_date) THEN 1 ELSE 0 END) AS has_txn_in_first_3_days,
MAX(CASE WHEN vt.txn_date = DATEADD(day, 7, c.join_date) THEN 1 ELSE 0 END) AS is_active_d7
FROM cohort_base c
-- LEFT JOIN: phải lấy tất cả User từ bảng cohort_base. Nếu dùng JOIN thường, những user không giao dịch sẽ bị loại bỏ khỏi báo cáo -> Sai mẫu số (Total Users).
LEFT JOIN valid_txns vt ON c.user_id = vt.user_id
GROUP BY c.user_id, c.cohort_month, c.join_date -- Bắt buộc phải có vì dùng hàm aggregate MAX().
),
streak_base AS (
SELECT DISTINCT
vt.user_id,
vt.txn_date
FROM valid_txns vt
JOIN cohort_base c ON vt.user_id = c.user_id
WHERE vt.txn_date <= DATEADD(day, 13, c.join_date)
),
streak_grouping AS (
SELECT
user_id,
txn_date,
-- Giả sử User giao dịch các ngày: 1, 2, 3 (Liên tục). ROW_NUMBER sẽ là: 1, 2, 3.
-- Phép trừ Date - RowNumber: Ngày 1 - 1 = Ngày 0, Ngày 2 - 2 = Ngày 0, Ngày 3 - 3 = Ngày 0
-- Kết quả ra giống nhau (Ngày 0). Vậy chúng thuộc cùng 1 nhóm (Island).
-- Nếu User giao dịch ngày: 1, 3 (Gãy nhịp)" Ngày 1 - 1 = Ngày 0, Ngày 3 - 2 = Ngày 1. -> Kết quả khác nhau. Vậy chúng thuộc 2 nhóm khác nhau.
-- Đây là cách để hiểu được khái niệm "liên tiếp" (Consecutive).
DATEADD(day, -ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY txn_date), txn_date) AS grp_id
FROM streak_base
),
user_max_streak AS (
SELECT
user_id,
COUNT(*) AS streak_length
FROM streak_grouping
GROUP BY user_id, grp_id
),
streak_final_flag AS (
SELECT
c.user_id,
c.cohort_month,
-- ISNULL(..., 0) dùng để xử lý những user không có giao dịch nào (NULL) thì coi là streak = 0.
CASE WHEN ISNULL(MAX(ums.streak_length), 0) >= 5 THEN 1 ELSE 0 END AS has_streak_5
FROM cohort_base c
LEFT JOIN user_max_streak ums ON c.user_id = ums.user_id
GROUP BY c.user_id, c.cohort_month
)
SELECT
c.cohort_month,
COUNT(DISTINCT c.user_id) AS total_users, -- Mẫu số chung
-- KR1: D7 Retention
-- CAST(... AS FLOAT): Trong SQL Server, phép chia số nguyên (5/10) sẽ trả về 0. Phải ép kiểu về số thực để ra 0.5.
-- FORMAT(..., 'P'): Định dạng số 0.5 thành chuỗi "50.00%".
FORMAT(CAST(SUM(uf.is_active_d7) AS FLOAT) / COUNT(DISTINCT c.user_id), 'P') AS [KR1_D7_Ret (Target 8%)],
-- KR2: Streak 5+ Adoption
FORMAT(CAST(SUM(sf.has_streak_5) AS FLOAT) / COUNT(DISTINCT c.user_id), 'P') AS [KR2_Streak5 (Target 25%)],
-- KR3: D3 Drop-off Rate
-- Logic KR3: Vì ở trên ta tính has_txn (Có giao dịch - Tích cực), nhưng KR3 lại hỏi Drop-off (Rơi rụng - Tiêu cực). Nên công thức là: 1 - Active Rate = Drop-off Rate.
FORMAT(1.0 - (CAST(SUM(uf.has_txn_in_first_3_days) AS FLOAT) / COUNT(DISTINCT c.user_id)), 'P') AS [KR3_DropOff_D3 (Target 45%)]
FROM cohort_base c
LEFT JOIN user_flags uf ON c.user_id = uf.user_id
LEFT JOIN streak_final_flag sf ON c.user_id = sf.user_id
GROUP BY c.cohort_month
ORDER BY c.cohort_month;
