데이터베이스/SQL

[Big Query] RFM Segmentation Project

jpocket 2025. 4. 17. 23:28
반응형

1. 프로젝트 개요

🎯 목표

고객 세분화 및 타깃 마케팅을 위한 RFM 분석 수행

🛠️ 사용한 도구

BigQuery

💻 사용한 언어

SQL

🧾 분석 대상

고객의 구매 데이터

📊 분석 방법

RFM 분석 (Recency, Frequency, Monetary)

 

 

 

2. RFM 분석이란?

  • Recency (최근성): 고객이 마지막으로 구매한 시점으로부터 얼마나 시간이 지났는지
  • Frequency (빈도): 고객이 얼마나 자주 구매했는지
  • Monetary (금액): 고객이 얼마나 많은 금액을 지출했는지

세 가지 요소를 바탕으로 고객을 세분화하여, 각 그룹에 맞는 마케팅 전략을 세울 수 있도록 돕는 방법이다.

 

 

 

3. 학습한 내용

  • BigQuery 사용법: 대용량 데이터 처리 및 SQL 쿼리 최적화 기법을 학습하였다.
  • RFM 분석: 고객의 구매 행동을 기반으로 세분화하는 기법을 적용하여 실질적인 마케팅 전략에 활용할 수 있다.

 

 

 

4. 분석 방법

  1. 데이터 전처리:
    • 결측치 처리: 분석에 방해가 되는 결측치를 제거하거나 적절히 대체하여 데이터를 정리하였다.
    • 중복값 처리: 중복된 데이터가 분석에 영향을 미치지 않도록 제거하였다.
    • 오류값 처리: 잘못된 값이나 형식 오류를 수정하여 분석에 적합한 데이터로 정리하였다.
  2. RFM 분석을 통한 추가 Feature 추출:
    • 구매하는 제품의 다양성: 고객이 구매한 다양한 제품의 수를 측정하여, 고객이 여러 제품군을 구매하는지 확인하였다.
    • 평균 구매 주기: 고객이 평균적으로 얼마나 자주 구매하는지 계산하여, 재구매 주기를 파악하였다.
    • 구매 취소 경향성: 고객의 취소 패턴을 분석하여, 취소 빈도와 비율을 측정하였다. 이를 통해 고객의 충성도나 반응을 예측할 수 있었다.

 

 

 

5. 코드 개선 포인트 🔎


내 코드)

delete from `white-might-456101-t9.modulabs_project.data`
where Description = 'Next Day Carriage' or Description = 'High Resolution Image';

 

예시 답안)

DELETE
FROM project_name.modulabs_project.data
WHERE
Description LIKE '%Next Day Carriage%'
OR Description LIKE '%High Resolution Image%';

와일드카드 문자 %를 사용하는 것이 적절하다.

문제에서 요구한 것은 지정된 문자열이 아닌 해당 문자열을 포함하는 모든 데이터를 제거하는 코드였다.

 

 

 

 

 


 

내 코드)

SELECT MAX(DATE(InvoiceDate)) AS most_recent_date
FROM `white-might-456101-t9.modulabs_project.data`;

 

예시 답안)

SELECT 
    MAX(DATE(InvoiceDate)) OVER () AS most_recent_date,
    DATE(InvoiceDate) AS InvoiceDay,
    *
FROM project_name.modulabs_project.data;

OVER() 구문이 없다고 해서 잘못된 코드는 아니다.

OVER() 구문의 유무는 분석 목적에 따라 달라지며, 둘 다 올바른 문법이다.

 

 

 

 

 

 


내 코드)

CREATE OR REPLACE TABLE`white-might-456101-t9.modulabs_project.user_data` AS
WITH TransactionInfo AS (
  SELECT
    CustomerID,
count(case when InvoiceNo LIKE 'C%' then 1 end) AS cancel_frequency,
COUNT(InvoiceNo) AS total_transactions
  FROM `white-might-456101-t9.modulabs_project.data`
group by CustomerID
)

SELECT u.*, t.* EXCEPT(CustomerID), round( (t.cancel_frequency / t.total_transactions)*100, 2) AS cancel_rate
FROM `white-might-456101-t9.modulabs_project.user_data` AS u
LEFT JOIN TransactionInfo AS t
ON u.CustomerID = t.CustomerID;

 

예시 답안)

 

CREATE OR REPLACE TABLE `project_name.modulabs_project.user_data` AS

WITH TransactionInfo AS (
  SELECT
    CustomerID,
    COUNT(DISTINCT InvoiceNo) AS total_transactions,
    COUNT(DISTINCT CASE WHEN InvoiceNo LIKE 'C%' THEN InvoiceNo END) AS cancel_frequency
  FROM `project_name.modulabs_project.data`
  GROUP BY CustomerID
)

SELECT u.*, t.* EXCEPT(CustomerID), ROUND(cancel_frequency/total_transactions, 2) AS cancel_rate
FROM `project_name.modulabs_project.user_data` AS u
LEFT JOIN TransactionInfo AS t
ON u.CustomerID = t.CustomerID;

올바른 방식은 InvoiceNo 자체를 기준으로 중복 제거 후 카운트하는 것이다.

C로 시작하는 InvoiceNo는 1이 되어, 전체 행 중에서 1인 행만 카운트하여 거래 수를 셀 수 있다고 판단하였다.

이는 거래 수가 아니라 거래한 상품 단위로 세는 것이 되어버린다.

따라서 1이 아닌 InvoiceNo로, distinct를 붙여 중복을 제거해주어야 한다.

 

반응형