DA

[Tech Blog #25 | Data Analytics] Phân Khúc Khách Hàng Với Mô Hình RFM: Tư Duy Định Lượng & Kỹ Thuật NTILE Trong SQL

0 views
[Tech Blog #25 | Data Analytics] Phân Khúc Khách Hàng Với Mô Hình RFM: Tư Duy Định Lượng & Kỹ Thuật NTILE Trong SQL

1. Đặt vấn đề: Cái bẫy của việc "Đối xử với mọi khách hàng như nhau"

Đã bao giờ bạn nhận được tin nhắn quảng cáo: "Tặng voucher 10.000đ cho đơn hàng tiếp theo" từ một nhãn hàng mà bạn vừa chi 50 triệu đồng để mua sắm tuần trước?
Hoặc ngược lại: Một khách hàng đã 2 năm không mở app bỗng nhiên nhận được email chúc mừng: "Cảm ơn bạn đã luôn đồng hành cùng chúng tôi"?

Đây là hậu quả của việc doanh nghiệp đối xử cào bằng với mọi khách hàng:

  • Khách hàng VIP chi hàng trăm triệu không nhận được đặc quyền tương xứng.
  • Khách hàng sắp rời bỏ (At-risk) không được cứu vãn kịp thời.
  • Ngân sách khuyến mãi (Voucher/Discount) bị rải mành mành vô ích cho những người chỉ thích săn sale giá rẻ mà không bao giờ quay lại.

Quy luật Pareto 80/20 chỉ ra rằng: Khoảng 20% lượng khách hàng trung thành thường đóng góp tới 80% tổng doanh thu của công ty.
Để tìm ra 20% khách hàng vàng này và biết chính xác cần phải làm gì với 80% còn lại, Data Analyst sử dụng một khung phân tích định lượng kinh điển: Mô hình RFM (Recency, Frequency, Monetary).


2. Giải mã 3 trụ cột của Mô hình RFM

RFM phân tích hành vi lịch sử giao dịch của từng khách hàng dựa trên 3 câu hỏi cốt lõi:

[RECENCY (R) - Độ mới]     ──> Lần mua hàng gần nhất cách đây bao nhiêu ngày?
                                (Càng mới mua gần đây -> Điểm R càng cao)

[FREQUENCY (F) - Tần suất] ──> Khách hàng đã phát sinh tổng cộng bao nhiêu đơn hàng?
                                (Càng mua nhiều lần -> Điểm F càng cao)

[MONETARY (M) - Giá trị]   ──> Khách hàng đã chi tiêu tổng cộng bao nhiêu tiền?
                                (Tổng chi tiêu càng lớn -> Điểm M càng cao)

Thang điểm từ 1 đến 5:

Chúng ta chia tập khách hàng thành 5 nhóm bằng nhau (mỗi nhóm 20%) cho từng chỉ số bằng cách cho điểm từ 1 (kém nhất) đến 5 (tốt nhất):

  • Điểm R (1 đến 5): Khách mới mua hôm qua →\rightarrow Điểm R = 5; Khách mua lần cuối từ 1 năm trước →\rightarrow Điểm R = 1. (Lưu ý: Số ngày càng nhỏ thì điểm R càng cao!)
  • Điểm F (1 đến 5): Mua 20 đơn →\rightarrow Điểm F = 5; Mua đúng 1 đơn duy nhất →\rightarrow Điểm F = 1.
  • Điểm M (1 đến 5): Chi tiêu 100 triệu →\rightarrow Điểm M = 5; Chi tiêu 100 nghìn →\rightarrow Điểm M = 1.

Mỗi khách hàng sẽ có một mã định danh 3 chữ số, ví dụ: 555 (Khách VIP tuyệt đối) hoặc 155 (Khách xịn nhưng sắp mất vào tay đối thủ!).


3. Bản đồ ma trận phân khúc khách hàng & Hành động kinh doanh

Nhóm khách hàngĐặc điểm điểm RFMTrạng thái hành viHành động chiến lược đề xuất
Champions (Khách hàng VIP)R: 4-5, F: 4-5, M: 4-5Mua gần đây, mua thường xuyên, chi tiền khủng.Chăm sóc 1-1, mời trải nghiệm sản phẩm mới sớm, không cần tặng voucher giảm giá sâu.
Loyal Customers (Trung thành)R: 3-4, F: 4-5, M: 3-5Mua đều đặn, giá trị tốt, gắn bó lâu dài.Chương trình tích điểm thành viên, gợi ý bán kèm (Cross-sell/Up-sell).
Potential Loyalists (Tiềm năng)R: 4-5, F: 2-3, M: 2-4Khách mới mua gần đây, chi tiêu khá, có triển vọng.Gửi email hướng dẫn sử dụng, tặng voucher cho đơn thứ 2 để tạo thói quen.
At Risk (Nguy cơ rời bỏ)R: 1-2, F: 4-5, M: 4-5Từng mua rất nhiều tiền nhưng đã lâu không quay lại!Báo động đỏ! Gọi điện CSKH hỏi thăm, gửi ưu đãi cá nhân hóa đặc biệt để kéo họ quay lại.
Hibernating / Lost (Ngủ đông)R: 1-2, F: 1-2, M: 1-2Đã rất lâu không mua, chỉ mua 1 lần giá trị thấp.Chạy chiến dịch email tự động chi phí thấp, nếu không phản hồi thì loại khỏi danh sách gửi tin để tiết kiệm ngân sách.

4. Thực hành thực chiến: Xây dựng Pipeline RFM hoàn chỉnh bằng SQL

Sử dụng CTE ([Tech Blog #17]) kết hợp hàm phân vị NTILE(5) trong SQL để phân nhóm khách hàng tự động:

-- Giả sử thời điểm chốt sổ phân tích là ngày 2026-09-30
WITH raw_rfm AS (
    -- Bước 1: Tính toán các giá trị thô R, F, M cho từng khách hàng
    SELECT 
        customer_id,
        -- Recency: Số ngày kể từ lần mua gần nhất đến ngày chốt sổ
        DATE_PART('day', '2026-09-30'::TIMESTAMP - MAX(order_date)) AS recency_days,
        -- Frequency: Tổng số đơn hàng đã hoàn thành
        COUNT(order_id) AS frequency_orders,
        -- Monetary: Tổng số tiền đã chi tiêu
        SUM(total_amount) AS monetary_value
    FROM 
        orders
    WHERE 
        status = 'COMPLETED'
    GROUP BY 
        customer_id
),

rfm_scores AS (
    -- Bước 2: Dùng hàm NTILE(5) chia đều thành 5 bậc điểm từ 1 đến 5
    SELECT 
        customer_id,
        recency_days,
        frequency_orders,
        monetary_value,
        -- Recency: Số ngày càng nhỏ thì điểm càng cao -> Dùng ORDER BY DESC để đảo ngược
        NTILE(5) OVER (ORDER BY recency_days DESC) AS r_score,
        -- Frequency & Monetary: Càng lớn điểm càng cao
        NTILE(5) OVER (ORDER BY frequency_orders ASC) AS f_score,
        NTILE(5) OVER (ORDER BY monetary_value ASC) AS m_score
    FROM 
        raw_rfm
),

segmented_customers AS (
    -- Bước 3: Ghép điểm và gán nhãn phân khúc bằng CASE WHEN
    SELECT 
        customer_id,
        recency_days,
        frequency_orders,
        monetary_value,
        r_score,
        f_score,
        m_score,
        -- Ghép chuỗi điểm: ví dụ '555', '155'
        CONCAT(r_score, f_score, m_score) AS rfm_combined,
        -- Gán nhãn phân khúc kinh doanh
        CASE 
            WHEN r_score >= 4 AND f_score >= 4 AND m_score >= 4 THEN '1. Champions (VIP)'
            WHEN r_score >= 3 AND f_score >= 3 AND m_score >= 3 THEN '2. Loyal Customers'
            WHEN r_score >= 4 AND f_score <= 2 THEN '3. New / Potential Loyalists'
            WHEN r_score <= 2 AND f_score >= 4 AND m_score >= 4 THEN '4. At Risk (Nguy cơ rời bỏ)'
            WHEN r_score <= 2 AND f_score <= 2 THEN '5. Lost / Hibernating'
            ELSE '6. Average Customers'
        END AS customer_segment
    FROM 
        rfm_scores
)

-- Bước 4: Thống kê tổng hợp số lượng và doanh thu theo từng phân khúc
SELECT 
    customer_segment,
    COUNT(customer_id) AS total_customers,
    ROUND(AVG(recency_days)::NUMERIC, 1) AS avg_recency_days,
    ROUND(AVG(frequency_orders)::NUMERIC, 1) AS avg_orders,
    ROUND(SUM(monetary_value)::NUMERIC, 0) AS total_revenue_vnd,
    ROUND(
        (SUM(monetary_value) / SUM(SUM(monetary_value)) OVER ()) * 100, 
        2
    ) AS revenue_contribution_pct
FROM 
    segmented_customers
GROUP BY 
    customer_segment
ORDER BY 
    total_revenue_vnd DESC;

5. Câu hỏi phỏng vấn thực tế (Interview Q&A)

Câu 1 (Mức độ: Entry / Junior)

Câu hỏi: "Mô hình RFM là gì? Tại sao chúng ta không phân loại khách hàng dựa trên một chỉ số duy nhất là Tổng chi tiêu (Monetary) cho đơn giản?"

Gợi ý trả lời:
"RFM phân loại khách hàng dựa trên 3 chiều: Độ mới (Recency), Tần suất (Frequency) và Tổng chi tiêu (Monetary).
Nếu chỉ dùng duy nhất chỉ số Monetary, chúng ta sẽ rơi vào điểm mù thời gian:
Một khách hàng từng chi 100 triệu mua hàng nhưng đã cách đây 3 năm và hiện đã chuyển sang mua của đối thủ vẫn sẽ bị xếp chung nhóm VIP với một khách hàng tuần nào cũng chi 5 triệu đều đặn.
Nhờ có thêm chiều Recency, chúng ta phân biệt được ngay: Ai là VIP đang hoạt động tích cực (R=5, M=5) và ai là VIP đang có nguy cơ rời bỏ (R=1, M=5) để kịp thời tung ra chiến dịch chăm sóc khách hàng cứu vãn doanh thu."

Câu 2 (Mức độ: Junior / Mid-level)

Câu hỏi: "Trong thực tế, khi dữ liệu bị lệch mạnh (ví dụ 75% khách hàng chỉ mua đúng 1 lần duy nhất), việc dùng hàm NTILE(5) trên cột Frequency sẽ gặp lỗi gì và cách xử lý chuẩn là gì?"

Gợi ý trả lời:
*"Hàm NTILE(5) cố gắng chia đều số dòng dữ liệu thành 5 nhóm có số lượng bằng nhau (mỗi nhóm 20%). Khi 75% khách hàng đều có cùng giá trị frequency = 1, hàm NTILE buộc phải chia các khách hàng có cùng giá trị 1 đơn này vào cả nhóm điểm 1, điểm 2 và điểm 3 một cách ngẫu nhiên. Điều này làm cho hai khách hàng có hành vi giống hệt nhau (đều mua 1 đơn) lại nhận điểm F khác nhau, gây sai lệch phân tích.
Cách xử lý chuẩn:
Thay vì dùng phân vị tương đối NTILE, chúng ta sẽ chuyển sang dùng Ngưỡng cố định theo nghiệp vụ (Rule-based Thresholds) bằng mệnh đề CASE WHEN:

  • F=1: Mua đúng 1 đơn.
  • F=2: Mua 2–3 đơn.
  • F=3: Mua 4–6 đơn.
  • F=4: Mua 7–10 đơn.
  • F=5: Mua trên 10 đơn.
    Cách này đảm bảo tính nhất quán tuyệt đối về mặt hành vi kinh doanh."*

6. Key Takeaways (Ghi nhớ nhanh)

  1. RFM là vũ khí chống lãng phí: Giúp doanh nghiệp chi tiền khuyến mãi đúng người, đúng thời điểm thay vì giảm giá đại trà.
  2. Quy tắc tính điểm Recency: Số ngày càng ít →\rightarrow Khách mua càng gần đây →\rightarrow Điểm RR càng cao (Dùng ORDER BY recency_days DESC trong NTILE).
  3. Cảnh giác cao độ với nhóm At Risk (R=1, F=5, M=5): Đây là những khách hàng giá trị cao sắp rời bỏ, cần ưu tiên nguồn lực chăm sóc hàng đầu.
  4. Kết hợp NTILE và Ngưỡng thực tế: Dùng NTILE khi dữ liệu phân phối đều; dùng CASE WHEN phân ngưỡng khi dữ liệu bị tập trung quá nhiều vào một giá trị duy nhất.
0Claps