WITH base AS (
SELECT
user_pseudo_id,
user_id,
platform,
datetime(timestamp_micros(event_timestamp), 'Asia/Seoul') as event_datetime,
date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), day) as event_date,
date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), week(monday)) as event_week,
date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), month) as event_month,
event_name,
event_params
FROM workspace.app_logs
),
user_visit_base AS (
SELECT DISTINCT
user_pseudo_id,
min(event_week) over(partition by user_pseudo_id) as first_visit_week,
event_week as visit_week
FROM base
),
user_visit_weekdiff AS (
SELECT
first_visit_week,
date_diff(visit_week, first_visit_week, week) as week_diff,
count(distinct user_pseudo_id) as visit_users
FROM user_visit_base
GROUP BY ALL
)
SELECT
first_visit_week,
week_diff,
visit_users,
first_value(visit_users) over(partition by first_visit_week order by week_diff asc rows between unbounded preceding and unbounded following) as cohort_size,
safe_divide(visit_users, first_value(visit_users) over(partition by first_visit_week order by week_diff asc rows between unbounded preceding and unbounded following)) as retention_rate
FROM user_visit_weekdiff
;
현재의 시점이 2023-01-20이고, 앱 사용 주기를 60일(2개월)로 정의하였으므로 유저별 최초 접속일과 기간별 접속일수를 활용하여 아래와 같은 로직으로 유저를 구분해 본다.
유저 그룹 | 용어적 정의 | 사업적 정의 | 쿼리적 정의 |
---|---|---|---|
New | 신규 유저 | 최근 60일 이내 새로 방문한 유저 | 유저의 최초 접속일 ≥ 지금으로부터 60일 이전 |
Current | 지속 유저 | 최근 60일 이내 재방문했고, 그 이전 60일 동안에도 방문한 유저 | 지금으로부터 60일 이내에 유저의 접속일수 1일 이상 |
AND 지금으로부터 120일 ~ 60일 이전 기간에 접속일수 1일 이상 |
|||
Resurrected | 부활 유저 | 최근 60일 이내 재방문했고, 그 이전 60일 동안에는 방문하지 않은 유저 | 지금으로부터 60일 이내에 유저의 접속일수 1일 이상 |
AND 지금으로부터 120일 ~ 60일 이전 기간에 접속일수 0일 |
|||
Dormant | 휴면 유저 | 최근 60일 이내 재방문하지 않은 유저 | 지금으로부터 60일 이내에 유저의 접속일수 0일 |
WITH base AS (
SELECT
user_pseudo_id,
user_id,
platform,
first_value(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul')) over(partition by user_pseudo_id order by event_timestamp asc rows between unbounded preceding and unbounded following) as first_visit_datetime,
last_value(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul')) over(partition by user_pseudo_id order by event_timestamp asc rows between unbounded preceding and unbounded following) as last_visit_datetime,
datetime(timestamp_micros(event_timestamp), 'Asia/Seoul') as event_datetime,
date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), day) as event_date,
date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), week(monday)) as event_week,
date_trunc(datetime(timestamp_micros(event_timestamp), 'Asia/Seoul'), month) as event_month,
event_name
FROM workspace.app_logs
),
user_click_payment_base AS (
SELECT DISTINCT
user_pseudo_id,
min(event_week) over(partition by user_pseudo_id) as first_click_payment_week,
event_week as click_payment_week
FROM base
WHERE event_name = 'click_payment'
),
user_payment_weekdiff AS (
SELECT
first_click_payment_week,
date_diff(click_payment_week, first_click_payment_week, week) as week_diff,
count(distinct user_pseudo_id) as click_payment_users
FROM user_click_payment_base
GROUP BY ALL
)
SELECT
first_click_payment_week,
week_diff,
click_payment_users,
first_value(click_payment_users) over(partition by first_click_payment_week order by week_diff asc rows between unbounded preceding and unbounded following) as cohort_size,
safe_divide(click_payment_users, first_value(click_payment_users) over(partition by first_click_payment_week order by week_diff asc rows between unbounded preceding and unbounded following)) as retention_rate
FROM user_payment_weekdiff
;