인프런 커뮤니티 질문&답변

권기영님의 프로필 이미지
권기영

작성한 질문수

BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)

3-14. 섹션 정리

바짝 스터디 3주차 과제 제출

작성

·

27

·

수정됨

0

연습문제 1번

select
*,
TRUNC(user_count / first_count, 3) AS ratio
from
(
  select
  *,
  first_value(user_count) over(order by week_diff asc) as first_count
  from
  (
    select
    week_diff,
    count(*) as user_count
    from
    (
      select
      *,
      date_diff(datetime_week, first_week, week) as week_diff
      from
      (
        select
        distinct
          event_date,
          user_pseudo_id,
          platform,
          datetime_week,
          -- event_name,
          first_value(datetime_week) over (partition by user_pseudo_id order by datetime_week asc) as first_week
        from
        (
          select 
          * except(firebase_screen,event_name),
          DATETIME_TRUNC(CAST(event_date AS DATE), WEEK) AS datetime_week,
          concat(firebase_screen,'_',event_name) as event_name 
          from
          (
            select 
            * except(event_param),
            max(if(event_param.key = 'firebase_screen',event_param.value.string_value , null)) as firebase_screen  
            from
            (
              select 
              event_date, event_timestamp, user_pseudo_id, platform, event_name, event_param 
              from `advanced.app_logs` 
              cross join unnest(event_params) as event_param 
              where event_date >= '2022-08-01' and event_date <= '2022-08-30'
            )
            group by all
          )
        )
      )
    )
    group by week_diff
  )
)
order by week_diff
;

연습문제2

  • 현재 시간에서 마지막 활동이 2주 이상 경과면 이탈

  • 마지막 활동이 현재 시간에서 1주 이내 인데 이전 활동과 갭이 2주이상이면 복귀

  • 마지막 action이 현재시간에서 1주내이고 이전 액션이 없다면 new

  • 나머진 active

select
user_pseudo_id,
case
  when DATETIME_DIFF(now, datetime_week, WEEK) >= 2 then 'dormant' 
  when DATETIME_DIFF(datetime_week, last_visit_week, WEEK) < 2 and DATETIME_DIFF(now, datetime_week, WEEK) < 2 then 'active'
  when DATETIME_DIFF(datetime_week, last_visit_week, WEEK) >= 2 and DATETIME_DIFF(now, datetime_week, WEEK) < 2 then 'resurrected'
  when DATETIME_DIFF(now, datetime_week, WEEK) < 2 and last_visit_week is null then 'new'
  else null
end as status
from
(
  select
  *,
  rank() over (partition by user_pseudo_id order by event_timestamp desc) as rank
  from
  (
    select
    distinct
      event_date,
      user_pseudo_id,
      platform,
      datetime_week,
      event_timestamp,
      -- event_name,
      -- first_value(datetime_week) over (partition by user_pseudo_id order by datetime_week asc) as first_week
      lag(datetime_week) over(partition by user_pseudo_id order by event_timestamp) as last_visit_week,
      CAST('2022-08-31 00:00:00' AS DATETIME) as now,
    from
    (
      select 
      * except(firebase_screen,event_name),
      DATETIME_TRUNC(CAST(event_date AS DATE), WEEK) AS datetime_week,
      concat(firebase_screen,'_',event_name) as event_name 
      from
      (
        select 
        * except(event_param),
        max(if(event_param.key = 'firebase_screen',event_param.value.string_value , null)) as firebase_screen  
        from
        (
          select 
          event_date, event_timestamp, user_pseudo_id, platform, event_name, event_param 
          from `advanced.app_logs` 
          cross join unnest(event_params) as event_param 
          where event_date >= '2022-08-01' and event_date <= '2022-08-30'
        )
        group by all
      )
    )
  )
  qualify rank=1
)
;

연습문제3, 연습문제4

  • 쿼리는 동일하게 사용하고 event_name을 변경하면서 리텐션이 가장 높은 값을 추적

  • click_restaurant의 리텐션이 가장 높아 이를 핵심 이벤트로 지정해야 하나 싶긴 한데 결과가 조금 이상해서 쿼리 점검 필요 해보임..

  • 아래 쿼리에서 event_name만 click_payment로 변경하면 click_payment의 weekly retention

select
*,
TRUNC(user_count / first_count, 3) AS ratio
from
(
  select
  *,
  first_value(user_count) over(order by week_diff asc) as first_count
  from
  (
    select
    week_diff,
    count(*) as user_count
    from
    (
      select
      *,
      date_diff(datetime_week, first_week, week) as week_diff
      from
      (
        select
        distinct
          user_pseudo_id,
          datetime_week,
          -- event_name,
          first_value(datetime_week) over (partition by user_pseudo_id order by datetime_week asc) as first_week
        from
        (
          select 
          *,
          DATETIME_TRUNC(CAST(event_date AS DATE), WEEK) AS datetime_week
          from
          (
            select 
              event_date, event_timestamp, user_pseudo_id, platform, event_name 
              from `advanced.app_logs` 
              where event_date >= '2022-08-01' and event_date <= '2022-08-30' and event_name='click_restaurant'
          )
        )
      )
    )
    group by week_diff
  )
)
order by week_diff
;

답변 1

0

안녕하세요, 인프런 AI 인턴입니다. 권기영님의 질문을 확인하였습니다. 질문에서 제공된 SQL 쿼리를 기반으로 리텐션 분석을 수행하고 계십니다. 몇 가지 핵심 사항과 권기영님께 도움이 될 만한 기존 질문과 답변을 안내해 드리겠습니다.

  1. 리텐션 분석의 기초 개념 정리:

    • 주차별 리텐션 계산을 위해 사용자가 처음 액티브한 주로부터 각 주차간 차이를 계산하고 있음을 확인했습니다. TRUNC를 통해 사용자 수 비율(ratio)을 구하는 전체 프로세스를 잘 따라가고 계십니다.
  2. 상태(Classification) 구분의 로직:

    • 데이터를 통해 사용자의 마지막 활동 시점을 기준으로 ‘dormant’, ‘active’, ‘resurrected’, ‘new’ 상태로 구분하는 로직이 잘 작성되었습니다. 이 부분은 사용자 흐름과 상태 변화를 이해하는데 유용합니다.
  3. 핵심 이벤트 조회 및 비율 분석:

    • 주차별로 특정 이벤트(click_restaurant 등)의 리텐션 비율을 비교하고, 이를 핵심 이벤트로 고려하자는 부분은 실무에서 중요한 인사이트입니다. 

이와 관련된 우리의 기존 데이터에서는 아래의 링크에서 공부할 수 있습니다. 같은 과정에서 제기된 질문이며, 비슷한 SQL 쿼리를 사용해 여러 상태를 분석하고 최적화를 진행하고 있습니다. 이 링크를 통해 더 나은 이해를 도모하시면 좋겠습니다:
-4-8. 지표 정의 연습 문제 풀이 답변 올려볼게요!

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해 드리고 있습니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏

추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

권기영님의 프로필 이미지
권기영

작성한 질문수

질문하기