inflearn logo
강의

Khóa học

Chia sẻ kiến thức

BigQuery(SQL) ứng dụng nâng cao (phân tích phễu, phân tích retention)

1-11. Phân tích phễu: Quyết định và tổ chức mục

app logs 데이터로 쿼리 연습

Đã giải quyết

16

dragonattack7955

6 câu hỏi đã được viết

0

안녕하세요 카일님, 잘 듣고 있습니다.

강의 말미에서 app logs 데이터로 쿼리 연습 해보라고 말씀주셔서 아래와 같이 몇 가지 연습해 보았습니다.

더 정확한, 효율적인 쿼리가 있는지,

틀린 부분이 있다면 피드백 부탁드립니다.


1. Screen 탐색량이 가장 많은 유저 찾기

질문: 어떤 유저가 앱 내 screen을 가장 많이 탐색했는가?

목적: 유저별 screen 조회 횟수를 집계하여 heavy user 탐색.

SELECT

  user_id,

  -- IF(event_params.key="firebase_screen", event_params.value.string_value, null) as screen,

  COUNT(*) as cnt_screen

FROM advanced.app_logs

CROSS JOIN UNNEST(event_params) as event_params

WHERE event_params.key='firebase_screen' 

GROUP BY ALL

HAVING user_id is not null

ORDER BY cnt_screen DESC

2. 날짜별 Screen 조회량 및 Screen 구성

질문: 날짜별 전체 screen 조회량은 어떻게 변화하며, 각 screen은 얼마나 조회되었는가?

목적: Screen View의 시계열 변화와 screen별 조회량을 동시에 분석. double check컬럼을 통해 정의한 screen들의 합계도 검증.

WITH unnest_table as (

SELECT

  *,

  IF(event_params.key="firebase_screen", event_params.value.string_value, null) as screen

FROM advanced.app_logs

CROSS JOIN UNNEST(event_params) as event_params

GROUP BY ALL

HAVING screen is not null)

SELECT

event_date,

count(screen) as total_screen_view,

COUNTIF(screen IN ('cart','welcome', 'food_category', 'home', 'search_result', 'food_detail', 'search','restaurant')) as double_check, --검증용 컬럼

 COUNTIF(screen='cart') as cart,

 COUNTIF(screen='welcome') as welcome,

 COUNTIF(screen='food_category') as food_category,

 COUNTIF(screen='home') as home,

 COUNTIF(screen='search_result') as serach_result,

 COUNTIF(screen='food_detail') as food_detail,

 COUNTIF(screen='search') as serach,

 COUNTIF(screen='restaurant') as restaurant

FROM unnest_table

GROUP BY ALL

3. Heavy User의 실제 Screen Journey 추적

질문: 특정 heavy user는 실제로 어떤 순서로 screen을 탐색하는가?

목적: Timestamp를 기준으로 사용자의 screen 이동 순서를 확인하고, firebaase screen 퍼널 순서 정의를 위한 탐색 수행.

SELECT

   TIMESTAMP_MICROS(event_timestamp) as timestamp,

  if(event_params.key="firebase_screen", event_params.value.string_value, null) as screen

FROM advanced.app_logs

CROSS JOIN UNNEST(event_params) as event_params

WHERE user_Id=57410

and

event_date between '2022-08-01' and '2023-12-30'

GROUP BY ALL

HAVING screen is not null

ORDER BY timestamp

limit 100


4. Cart 도달 유저 vs Non-Cart 유저의 Screen 탐색량 비교

질문: Cart를 한 번이라도 조회한 유저는 그렇지 않은 유저보다 평균적으로 더 많은 screen을 탐색하는가?

목적: 사용자를 has_cart 여부로 segmentation하고 두 그룹의 평균 screen 탐색량 비교.

WITH basic AS (

SELECT

  user_id,

  COUNT(*) AS screen_cnt_per_user,

  COUNTIF(event_params.value.string_value='cart') >0 AS has_cart

FROM advanced.app_logs

CROSS JOIN UNNEST(event_params) as event_params

WHERE event_params.key='firebase_screen'

GROUP BY user_id)

SELECT

  AVG(IF(has_cart, screen_cnt_per_user,NULL )) as avg_view_cart,

  AVG(IF( not has_cart, basic.screen_cnt_per_user, null)) as avg_view_non_cart

FROM basic


unnest 와 집계함수를 연속적으로 쓰려고 할 때나 unnest+집계함수+having 쓰려고 할 때는 반드시 with문으로 분리해서 사용해야 오류가 안 나는 것 같더라고요. 그러다 보니 쿼리가 길어지는데 더 가독성 좋은 쿼리 작성법이 있을 것 같습니다. ㅎㅎ

sql Google-Analytics firebase google-sheets bigquery

Câu trả lời 2

0

kyleschool

유정님 안녕하세요

unnest 와 집계함수를 연속적으로 쓰려고 할 때나 unnest+집계함수+having 쓰려고 할 때는 반드시 with문으로 분리해서 사용해야 오류가 안 나는 것 같더라고요. 그러다 보니 쿼리가 길어지는데 더 가독성 좋은 쿼리 작성법이 있을 것 같습니다. ㅎㅎ


이 말이 어떤 쿼리에서 발생한 걸까요? 말씀하신 경우가 항상 WITH를 써야 된다는 것은 아닐텐데 쿼리를 어떻게 바꾸셨는지 말씀해주시면 가이드를 드릴 수 있을 것 같아요.


그리고 이 문제들은 쿼리 작성도 좋지만, 데이터 결과를 보고 해석을 해보는 경험을 더 추천드려요! 해석을 잘 하는 것이 중요하기에 결과 보고 해석을 어떻게 할지 고민해보셔요(현상을 파악하고 그걸 토대로 가설을 떠올리면 좋아요)

0

communityai8509

안녕하세요, 인프런 AI 인턴입니다. 이유정님.

UNNEST와 집계 함수를 반드시 WITH문으로 분리해야 하는 것은 아닙니다. 다만 event_params가 배열 구조이기 때문에 먼저 행으로 펼친 뒤, 필요한 파라미터만 필터링하고 집계하는 단계로 나누면 쿼리의 가독성과 검증이 좋아집니다.

작성하신 쿼리에서 특히 확인하면 좋은 부분은 다음과 같습니다.

  • firebase_screen 값은 screen_view 이벤트에서만 집계하는 것이 정확합니다. 다른 이벤트에도 동일한 파라미터가 포함될 수 있기 때문입니다.
  • 로그인 여부에 따라 user_idNULL일 수 있으므로, 전체 사용자를 분석하려면 user_pseudo_id를 사용하는 것도 고려해볼 수 있습니다.
  • UNNEST(event_params) 후에는 event_params.key = 'firebase_screen' 조건을 먼저 적용하면 불필요하게 펼쳐지는 데이터를 줄일 수 있습니다.
  • Heavy user의 화면 이동 순서를 확인할 때는 event_timestamp를 기준으로 정렬하면 되며, 한국 시간으로 확인하려면 DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') 형태를 사용할 수 있습니다.
  • WITH문은 오류를 피하기 위한 필수 조건이라기보다, UNNEST → 필터링 → 사용자별 집계 → 그룹별 비교처럼 분석 단계를 명확하게 나누기 위한 방법입니다.

예를 들어 공통으로 사용할 화면 데이터는 다음과 같이 한 번 분리해두면 이후 쿼리를 간결하게 작성할 수 있습니다.

WITH screen_events AS (
  SELECT
    event_date,
    event_timestamp,
    user_id,
    user_pseudo_id,
    event_param.value.string_value AS screen
  FROM advanced.app_logs
  CROSS JOIN UNNEST(event_params) AS event_param
  WHERE event_name = 'screen_view'
    AND event_param.key = 'firebase_screen'
)

SELECT
  user_pseudo_id,
  COUNT(*) AS screen_cnt
FROM screen_events
GROUP BY user_pseudo_id
ORDER BY screen_cnt DESC;

이후 날짜별 집계나 cart 도달 여부 비교도 screen_events를 재사용하여 작성할 수 있습니다. 즉, 쿼리가 길어지는 것이 반드시 나쁜 것은 아니며, 각 CTE가 하나의 분석 단계만 담당하도록 구성하면 오히려 유지보수하기 쉬운 형태가 됩니다.

관련된 기존 답변을 참고해 주세요.

원본 URL: https://www.inflearn.com/questions/1402041

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

[과제] 연습문제 쿼리 작성했습니다!

0

18

2

6-1. 강의 최종 과제 제출합니다.

0

55

3

3-13 리텐션 과제 제출합니다

0

113

3

3-13. 리텐션 연습과제 제출합니다.

0

84

4

최종 과제 제출

0

72

3

Weekly Retention 과제 작성하였습니다.

0

65

2

3-10 강의 14분경 코호트 해석 질문드립니다.

0

76

2

Weekly 및 Monthly Retention 과제 제출합니다.

0

73

2

[과제] 퍼널 쿼리 PIVOT 테이블 작성

0

74

2

최종 과제 제출

0

143

3

BigQuery 활용편 18강 질문있습니다!

0

111

1

리텐션 공부하다가 궁금한게 생겨 질문드립니다

0

116

2

안녕하세요 강사님 코호트 쿼리 공부하다가 의문점이 생겨서 문의드립니다

0

108

2

biquery 테이블 생성 오류 이슈

0

106

2

동일하게 쿼리를 작성했는데 화면과 다른 값이 나옵니다

0

112

2

[과제] 퍼널 PIVOT 테이블 작성하기

0

107

2

array 등

0

92

2

N day 리텐션 쿼리 관련 질문

0

99

2

이동평균 계산 시 order by 기본값은 뭔가요?

0

95

2

윈도우 연습문제 1번 질문

0

92

1

user_id에 NULL이 나오는데 정상인가요?

0

111

2

3-13 리텐션 과제 제출

0

144

2

최종 과제 제출

0

189

3

weekly retention 구하기 과제

0

131

2