app logs 데이터로 쿼리 연습
안녕하세요 카일님, 잘 듣고 있습니다.
강의 말미에서 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 DESC2. 날짜별 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 ALL3. 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 1004. 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 basicunnest 와 집계함수를 연속적으로 쓰려고 할 때나 unnest+집계함수+having 쓰려고 할 때는 반드시 with문으로 분리해서 사용해야 오류가 안 나는 것 같더라고요. 그러다 보니 쿼리가 길어지는데 더 가독성 좋은 쿼리 작성법이 있을 것 같습니다. ㅎㅎ
Câu trả lời 2
0
유정님 안녕하세요
unnest 와 집계함수를 연속적으로 쓰려고 할 때나 unnest+집계함수+having 쓰려고 할 때는 반드시 with문으로 분리해서 사용해야 오류가 안 나는 것 같더라고요. 그러다 보니 쿼리가 길어지는데 더 가독성 좋은 쿼리 작성법이 있을 것 같습니다. ㅎㅎ
이 말이 어떤 쿼리에서 발생한 걸까요? 말씀하신 경우가 항상 WITH를 써야 된다는 것은 아닐텐데 쿼리를 어떻게 바꾸셨는지 말씀해주시면 가이드를 드릴 수 있을 것 같아요.
그리고 이 문제들은 쿼리 작성도 좋지만, 데이터 결과를 보고 해석을 해보는 경험을 더 추천드려요! 해석을 잘 하는 것이 중요하기에 결과 보고 해석을 어떻게 할지 고민해보셔요(현상을 파악하고 그걸 토대로 가설을 떠올리면 좋아요)
0
안녕하세요, 인프런 AI 인턴입니다. 이유정님.
UNNEST와 집계 함수를 반드시 WITH문으로 분리해야 하는 것은 아닙니다. 다만 event_params가 배열 구조이기 때문에 먼저 행으로 펼친 뒤, 필요한 파라미터만 필터링하고 집계하는 단계로 나누면 쿼리의 가독성과 검증이 좋아집니다.
작성하신 쿼리에서 특히 확인하면 좋은 부분은 다음과 같습니다.
firebase_screen값은screen_view이벤트에서만 집계하는 것이 정확합니다. 다른 이벤트에도 동일한 파라미터가 포함될 수 있기 때문입니다.
- 로그인 여부에 따라
user_id가NULL일 수 있으므로, 전체 사용자를 분석하려면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가 하나의 분석 단계만 담당하도록 구성하면 오히려 유지보수하기 쉬운 형태가 됩니다.
관련된 기존 답변을 참고해 주세요.
1-9. 퍼널 SQL 쿼리 작성하기
UNNEST로 이벤트 파라미터를 펼친 뒤 필요한 값을 피벗하고, 날짜 조건과 이벤트명 조건을 적용하는 방법을 설명하고 있습니다. 특히 필터 조건 누락이나 이벤트명 오타로 결과가 달라지는 사례를 확인할 수 있습니다.[과제] 퍼널 쿼리(피벗테이블 적용) 작성 완료
MAX(IF(...)),UNNEST,CASE WHEN,COUNT(DISTINCT ...)를 조합하여 이벤트 데이터를 집계하는 예시가 포함되어 있습니다.[1-9. 퍼널 SQL 쿼리 작성하기] 집계데이터 pivot쿼리
집계된 데이터를 피벗하는 방식과 동적 피벗을 추가로 학습할 수 있는 참고 자료를 안내하고 있습니다.
원본 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

