묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
3-7. Weekly 리텐션 쿼리 작성 및 질문
안녕하세요.Weekly로 리텐션 쿼리 아래와 같이 작성해 보았습니다.한가지 질문할 점은 event_week 기간 동안 한번 이상 접속을 한다고 하더라도 user_psuedo_id는 한번으로 집계되는지 궁금합니다!그리고 작성한 쿼리문을 좀 더 나은 방향으로 수정하면 좋은 방향이 있다면 언제든 말씀 부탁드릴께요! 강의 정말 잘 듣고 있습니다 :)===작성한 쿼리문===WITH base AS ( SELECT DISTINCT user_id, DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), "Asia/Seoul")) AS event_date, user_pseudo_id FROM advanced.app_logs WHERE event_date BETWEEN "2022-08-01" AND "2022-11-03" ), diff_of_week_data AS ( SELECT *, DATE_DIFF(event_week, first_week, week) AS diff_of_week FROM( SELECT DISTINCT user_pseudo_id, MIN (DATE_TRUNC(event_date,WEEK(MONDAY))) OVER (PARTITION BY user_pseudo_id) AS first_week, DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week FROM base ) ) SELECT *, SAFE_DIVIDE(cnt, first_value_cnt) AS retention_ratio FROM( SELECT *, FIRST_VALUE(cnt) OVER (ORDER BY diff_of_week) AS first_value_cnt FROM( SELECT diff_of_week, COUNT(user_pseudo_id) AS cnt FROM diff_of_week_data GROUP BY diff_of_week ) ) ORDER BY diff_of_week
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
리텐션 분석 과제
리텐션 분석 과제 노션 문서에 정리해서 공유드립니다~문서 링크
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
3-13 4번 문제 풀어보았습니다
4. Core Event를 "click_payment"라고 설정하고 Weekly Retention을 구해주세요. WITH base AS( SELECT event_date, event_timestamp, user_pseudo_id, event_name, MAX(IF(ep.key = 'firebase_screen', ep.value.string_value, NULL)) AS firebase_screen, MAX(IF(ep.key = 'food_id', ep.value.int_value, NULL)) AS food_id, MAX(IF(ep.key = 'session_od', ep.value.string_value, NULL)) AS session_od FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS ep GROUP BY ALL ), payment AS( SELECT user_pseudo_id, event_timestamp, event_date, event_name, --firebase_screen, FROM base WHERE event_name = 'click_payment' ORDER BY event_date ), payment_first_week AS( SELECT *, DATE_TRUNC(MIN(event_date) OVER(PARTITION BY user_pseudo_id), WEEK(MONDAY)) AS first_week, DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week FROM( SELECT * EXCEPT(event_timestamp, event_date), DATE(DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul')) AS event_date FROM payment ) ), payment_user_cnt AS( SELECT diff_of_week, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM( SELECT *, DATE_DIFF(event_week, first_week, WEEK) AS diff_of_week FROM payment_first_week ) GROUP BY diff_of_week ORDER BY diff_of_week ) ############################### 리텐션 비율 구하기 ############################### SELECT *, SAFE_DIVIDE(user_cnt, first_week_user_cnt) AS retention_rate FROM( SELECT *, FIRST_VALUE(user_cnt) OVER(ORDER BY diff_of_week) AS first_week_user_cnt FROM payment_user_cnt ) 여기까지는 payment 테이블 WHERE절에 event_name으로 "click_payment" 조건을 걸어준 것 빼곤 강의의 코드를 거의 그대로 사용했습니다. 결과는 이렇게 나왔고, 저는 diff_of_week가 4일 때 갑자기 user_cnt가 상승했다가 5일 때 다시 이전 수치로 돌아간 것에 주목했습니다(약 18% 상승). SELECT event_week, COUNT(DISTINCT user_pseudo_id) AS user_cnt FROM( SELECT *, DATE_DIFF(event_week, first_week, WEEK) AS diff_of_week FROM payment_first_week ) WHERE diff_of_week = 4 GROUP BY event_week ORDER BY user_cnt DESC 그래서 diff_of_week가 4일 때의 "click_payment" 이벤트를 발생시킨 유저의 수를 추출해보았습니다. 결과를 보았을 때, 2022-10-31 ~ 2023-01-09의 유저 수가 많음을 확인하였고 이는, 해당 기간이 첫 주문 후 4주가 지난 사람들의 재주문 건수가 많았을 것이라는 생각이 들었습니다. ##################### 해당 날짜, 이전, 이후의 데이터 추출 #################### # target_date 테이블: 해당 날짜를 만족하는 행만 추출 , target_date AS( SELECT * FROM base WHERE user_pseudo_id IN( SELECT user_pseudo_id FROM payment_first_week WHERE first_week BETWEEN '2022-10-03' AND '2022-12-12' ) ORDER BY user_pseudo_id, event_timestamp # before_target_date 테이블: 해당 날짜 이전 ), before_target_date AS( SELECT * FROM base WHERE user_pseudo_id IN( SELECT user_pseudo_id FROM payment_first_week WHERE first_week BETWEEN '2022-08-01' AND '2022-10-02' ) ORDER BY user_pseudo_id, event_timestamp # after_target_date 테이블: 해당 날짜 이후 ), after_target_date AS( SELECT * FROM base WHERE user_pseudo_id IN( SELECT user_pseudo_id FROM payment_first_week WHERE first_week BETWEEN '2022-12-13' AND '2023-12-31' ) ORDER BY user_pseudo_id, event_timestamp ) ################ click_payment를 발생시킨 유저와 그 때의 날짜 추출 ################ # payment_users 테이블: 해당 날짜에서 event_name칼럼에 "click_payment"를 가지고 있는 user_pseudo_id와 그 때의 event_date를 추출 , payment_users_target_date AS( SELECT event_date, user_pseudo_id FROM( SELECT *, CASE WHEN event_name = 'click_payment' THEN 1 ELSE 0 END AS payment_user FROM target_date ) WHERE payment_user = 1 ) # payment_users_before 테이블: 해당 날짜 이전의 payment user의 정보 ,payment_users_before AS( SELECT event_date, user_pseudo_id FROM( SELECT *, CASE WHEN event_name = 'click_payment' THEN 1 ELSE 0 END AS payment_user FROM before_target_date ) WHERE payment_user = 1 ) # payment_users_after 테이블: 해당 날짜 이후의 payment user의 정보 ,payment_users_after AS( SELECT event_date, user_pseudo_id FROM( SELECT *, CASE WHEN event_name = 'click_payment' THEN 1 ELSE 0 END AS payment_user FROM after_target_date ) WHERE payment_user = 1 ) 그래서 전체 날짜를 위의 해당 날짜와 그 전, 후 3개로 나누어 해당 기간의 정보만을 담는 테이블을 생성하고, 각 기간에 "click_payment" 이벤트를 가지고 있는 유저의 user_pseudo_id와 그 때의 event_date를 추출하였습니다.################ 3개의 기간동안 사람들이 주문한 음식의 food_id 추출 ################ # 해당 기간동안 사람들이 주문한 food_id , food_cnt_target_date AS( SELECT food_id, COUNT(*) AS food_cnt FROM target_date td JOIN payment_users_target_date pu ON td.user_pseudo_id = pu.user_pseudo_id AND td.event_date = pu.event_date WHERE event_name = "click_cart" GROUP BY food_id ORDER BY food_cnt DESC --ORDER BY td.user_pseudo_id, event_timestamp ), # 해당 기간 이전 사람들이 주문한 food_id food_cnt_before_target AS( SELECT food_id, COUNT(*) AS food_cnt FROM before_target_date td JOIN payment_users_before pu ON td.user_pseudo_id = pu.user_pseudo_id AND td.event_date = pu.event_date WHERE event_name = "click_cart" GROUP BY food_id ORDER BY food_cnt DESC ), # 해당 기간 이후 사람들이 주문한 food_id food_cnt_after_target AS( SELECT food_id, COUNT(*) AS food_cnt FROM after_target_date td JOIN payment_users_after pu ON td.user_pseudo_id = pu.user_pseudo_id AND td.event_date = pu.event_date WHERE event_name = "click_cart" GROUP BY food_id ORDER BY food_cnt DESC ) 위에서 구한 id와 date를 이용해 세 기간동안 사람들이 주문한 음식과 음식 별 건수를 추출하였습니다. 전체 데이터를 살펴본 결과, "click_payment"는 항상 주문 마지막에 발생하는 이벤트이며, 이 row에는 food_id는 없고, "click_cart" 이벤트를 발생시켰을 때 해당 주문건에 대한 food_id가 row에 포함되어 있어 event_name을 "click_cart"로 지정하였습니다. ################ 각 food_id 별 해당 기간, 이전, 이후의 주문 건수 카운트 ################ , total_cnt AS( SELECT td.food_id, btd.food_cnt AS food_cnt_before_target_date, td.food_cnt AS food_cnt_target_date, atd.food_cnt AS food_cnt_after_target_date FROM food_cnt_target_date td JOIN food_cnt_before_target btd ON td.food_id = btd.food_id JOIN food_cnt_after_target atd ON td.food_id = atd.food_id ) ################ 각 food_id 별 해당 기간, 이전, 이후의 주문 건수 비율 ################ SELECT food_id, food_cnt_before_target_date, ROUND(SAFE_DIVIDE(food_cnt_before_target_date, SUM(food_cnt_before_target_date) OVER()), 4) AS rate_before, food_cnt_target_date, ROUND(SAFE_DIVIDE(food_cnt_target_date, SUM(food_cnt_target_date) OVER()), 4) AS rate_target, food_cnt_after_target_date, ROUND(SAFE_DIVIDE(food_cnt_after_target_date, SUM(food_cnt_after_target_date) OVER()), 4) AS rate_after FROM total_cnt ORDER BY rate_target DESC세 기간동안 사람들이 주문한 food_id와 그 횟수, 비율을 구해보았습니다. 각 음식의 비율은 매우 적지만 target_date를 기준으로 정렬해 보았을 때, 확실히 해당 기간동안 주문량이 높고 나머지 기간에는 주문량이 낮은 음식들이 존재했습니다(ex. 1438, 1516 등). 하지만, 이것이 4주전 주문자들의 실제 재주문 결과인지, 단지 해당기간 동안 신규 유저가 늘었기 때문인지 확실하지 않다고 생각문자와 그 외 기간동안의 신규 주문자를 비교해 보았습니다. SELECT new_user_target_date, COUNT(*) AS new_user_cnt FROM( SELECT CASE WHEN first_week BETWEEN '2022-10-31' AND '2023-01-09' THEN 1 ELSE 0 END AS new_user_target_date FROM payment_first_week ) GROUP BY new_user_target_date 해당 기간의 신규 유저수는(new_user_target_date = 1) 6261명, 그 외 기간의 신규 유저수는 6898명으로, 전체 기간 대비 해당 기간의 비율을 고려해보았을 때, 신규 유저가 크게 늘었다고 보기 어려웠습니다. 따라서, 2022~10-03 ~ 2022-12-12일이 포함된 주차에 첫 주문을 한 고객들의 만족도가 높았거나, 그 당시에 시행했던 첫 주문 관련 마케팅, 광고 효과가 좋았을 것이라고 판단할 수 있었습니다. ** 앱 로그 데이터를 처음 접했기 때문에 코드 오류나 논리적인 비약이 있을 것이라고 생각하지만, 단지 Weekly Retention에 WHERE 조건을 추가하는 것에 그치기 아쉬워서(?) 의식의 흐름대로 분석해보았습니다.
-
해결됨초보자를 위한 BigQuery(SQL) 입문
JOIN 5번 문제 질문 있습니다!
안녕하세요, 카일님! 수업 잘 듣고 있습니다!문제 해설 보기 전 혼자 풀었을 때, 저는 아래와 같이 쿼리를 작성했어요. 서브쿼리 안에 필요한 컬럼만 넣고 보면서 쓰는 게 편하더라고요. 제 쿼리로 쓰면 데이터를 더 많이 처리하게 되는 건지 궁금해서 질문합니다!
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
3-7. 리텐션 쿼리 작성해보기(Weekly, Montly)
Weekly 리텐션 분석#Weekly 리텐션 with base as ( select distinct user_id, user_pseudo_id, event_name, date(datetime(timestamp_micros(event_timestamp), "Asia/Seoul")) as event_date, datetime(timestamp_micros(event_timestamp), "Asia/Seoul") as event_datetime, from `advanced.app_logs` where event_date between "2022-08-01" and "2022-11-03" ), retain_base as ( select user_pseudo_id, event_week, first_week, date_diff(event_week, first_week, week) as diff_of_week from ( select distinct user_pseudo_id, date_trunc(event_date, week(monday)) as event_week, date_trunc(min(event_date) over(partition by user_pseudo_id),week(monday)) as first_week, -- 유저의 첫 접속 주차 from base ) ) select diff_of_week, user_cnt, first_value(user_cnt) over(order by diff_of_week) as first_user_cnt from ( select diff_of_week, count(distinct user_pseudo_id) as user_cnt from retain_base group by diff_of_week ) order by diff_of_week Montly 리텐션 분석#Montly 리텐션 with base as ( select distinct user_id, user_pseudo_id, event_name, date(datetime(timestamp_micros(event_timestamp), "Asia/Seoul")) as event_date, datetime(timestamp_micros(event_timestamp), "Asia/Seoul") as event_datetime, from `advanced.app_logs` where event_date between "2022-08-01" and "2022-11-03" ), retain_base as ( select user_pseudo_id, event_month, first_month, date_diff(event_month, first_month, month) as diff_of_month from ( select distinct user_pseudo_id, date_trunc(event_date, month) as event_month, date_trunc(min(event_date) over(partition by user_pseudo_id),month) as first_month, -- 유저의 첫 접속 주차 from base ) ), month_retain as ( select diff_of_month, user_cnt, first_value(user_cnt) over(order by diff_of_month) as first_user_cnt from ( select diff_of_month, count(distinct user_pseudo_id) as user_cnt from retain_base group by diff_of_month ) ) select diff_of_month, user_cnt, first_user_cnt, round(safe_divide(user_cnt, first_user_cnt),3) as retention_rate from month_retain order by diff_of_month 위클리랑 먼슬리 리텐션 쿼리 작성했습니다~
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
FRAME 연습 마지막 AVG 문제 소수점에 대하여 여쭤볼게 있습니다!
문제풀이를 해가던 도중마지막 ROWS BETWEEN을 이용한 5가지 AMOUNT의 AVG를 구할때 소수점이 나오는데SELECT절에 적힌 WINDOW 함수 쿼리를ROUND, FLOOR 을 사용해서 감싸줘도 작동은 하지만 소수점이 사라지지 않는데 혹시 그 이유가 뭔가요???
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
디스코드 접속 관련
질문을 남겨주실 때 아래 부분을 같이 남겨주시면 더 빠르게 상황을 파악하고 답변드릴 수 있어요 🙂어떤 강의를 들으면서 발생했나요? BigQuery 활용편어떤 문제가 생겼나요? 디스코드 접속 불가어떤 시도를 해보셨나요? 강의 중 제공되는 링크로 디스코드 접속시 무한 로딩 발생어떤 쿼리를 사용했나요? - 환경이 어떻게 되나요?(윈도우, 맥 중 택1, 크롬 같은 웹브라우저 환경) 윈도우
-
해결됨초보자를 위한 BigQuery(SQL) 입문
5-6. 2번 연습문제 질문입니다!
안녕하세요. 강의에서는LEFT JOIN ...ON ...하고 나서 WHERE type1='Grass'으로 먼저 필터링을 하신 것 같은데요!아래 처럼 GROUP BY - HAVING으로 해도 결과는 동일한데,GROUP BY 보다 WHERE를 먼저 했을 때 수행 속도 등의 이득이 있는지 궁금합니다!SELECT type1, COUNT(type1) AS pokemon_cnt FROM ( SELECT id, trainer_id, pokemon_id, status FROM `basic.trainer_pokemon` WHERE status IN ('Active', 'Training') ) AS tp LEFT JOIN `basic.pokemon` AS p ON tp.pokemon_id = p.id GROUP BY type1 HAVING type1 = 'Grass'
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
강의 중간에 쿼리 복사 붙여넣기 해야하는 부분들
안녕하세요!기본편에 이어 활용편을 열심히 듣고 있는 학생입니다. 제 브라우저나 pc의 문제인지는 모르겠지만, 강의 중간에 쿼리를 복사 붙여넣기 해야 되는 부분들이 있을 때, 인프런 플레이어에서 문자인식 후 복사하는 기능을 제공하지 않습니다..그래서 따로 캡쳐를 따서 문자를 인식한 후, 복사 붙여넣기를 해야 하는데요. 이럴 때도 정확도가 좋지 않아서 일일이 수기로 다 수정을 해야합니다. 혹시 강의 중간에 복사 붙여넣어 사용해야할 쿼리가 있다면 혹시 해당 강의에 강의 자료 부분에 텍스트로 올려놔주실 수 있을까요? 그렇다면 많은 학생들이 쿼리를 쉽게 복사, 붙여넣어 강의를 빠르게 들을 수 있을 것 같습니다. 항상 열심히 강의 해주시고 답변해주셔서 감사합니다!
-
해결됨초보자를 위한 BigQuery(SQL) 입문
battle 테이블 오류
battle 파일을 반디집으로 압축 풀기하고 업로드 했는데 다음과 같은 오류가 뜹니다 어떻게 해야할까요?
-
해결됨초보자를 위한 BigQuery(SQL) 입문
2-6. 연습문제 12번
연습문제 풀던 중에 궁금한 게 생겨서 여쭤봅니다!12번에서 단일 포켓몬 중 많은 타입 1을 구할 때, 지금 데이터에선 type2가 null인 경우만 있지만, type1도 null인 경우도 있다고 가정하면,where (type2 is null) or (type1 is null) 처럼 or 조건으로 표현하면 될까요?
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
Retention 쿼리를 작성하면서.. 궁금한점이 있습니다.
Weekly Retention은 diff_of_week 을 활용하여, 시간의 경과에 따른 리텐션 변화를 구합니다. 따라서, 제가 생각했을 때, Weekly Retention을 구하는 쿼리에서는 다음과 같은 가정을 하고 진행한 것이 아닐까? 라는 생각이 들었습니다.주차별로(시간에 따라) 활동 중인 사용자 수는 달라질 것이다.user_type에 따라 활동 중인 사용자 수는 차이가 있을 것이다.2.의 경우는 만약의 신규/복귀... 유저를 구분한다면, 해당 가설을 기반으로, Weekly Retention을 구하는 행위를 한 것이 아닐까? 라는 생각이 들었습니다.(추가 궁금증)Retention에 영향을 주는 인자를 분석하는 경우도 있을까요? (실무에서) 저는 Retention을 분석하기 전에, Retention과 관련이 높은 것이 무엇일지, 가설을 세우고 검정을 해보았습니다. 가설: 방문일수는 Retention에 높은 상관관계를 가진다.데이터 범위: 2022-08-01 ~ 2022-11-01D7_retention : (bool) 사용자의 첫번째 이벤트 시점 ~ 7일 이후에도 활동을 하면, 1 아니면 0D30_retention : (bool) 사용자의 첫번째 이벤트 시점 ~ 30일 이후에도 활동을 하면, 1아니면 0import os from google.cloud import bigquery from google.oauth2 import service_account import pandas as pd import statsmodels.api as sm from scipy.stats import pointbiserialr import numpy as npos.environ['GOOGLE_APPLICATION_CREDENTIALS'] = './service_account.json' key_path = './service_account.json' credentials = service_account.Credentials.from_service_account_file( key_path, scopes = ["https://www.googleapis.com/auth/cloud-platform"], ) client = bigquery.Client(credentials=credentials, project=credentials.project_id, location="US")query = """ WITH user_visits AS ( SELECT user_pseudo_id, COUNT(DISTINCT event_date) AS visit_days FROM advanced.app_logs WHERE event_date BETWEEN '2022-08-01' AND '2022-11-01' GROUP BY user_pseudo_id ), retention_data AS ( SELECT user_pseudo_id, MIN(event_date) AS first_event_date, MAX(event_date) AS last_event_date, CASE WHEN MAX(event_date) >= DATE_ADD(MIN(event_date), INTERVAL 7 DAY) THEN 1 ELSE 0 END AS D7_retention, CASE WHEN MAX(event_date) >= DATE_ADD(MIN(event_date), INTERVAL 30 DAY) THEN 1 ELSE 0 END AS D30_retention FROM advanced.app_logs WHERE event_date BETWEEN '2022-08-01' AND '2022-11-01' GROUP BY user_pseudo_id ), combined_data AS ( SELECT v.user_pseudo_id, v.visit_days, r.D7_retention, r.D30_retention FROM user_visits v JOIN retention_data r ON v.user_pseudo_id = r.user_pseudo_id ) SELECT * FROM combined_data; """df = client.query(query).to_dataframe() df['visit_days'] = pd.to_numeric(df['visit_days'], errors='coerce').astype(np.float64) df['D7_retention'] = pd.to_numeric(df['D7_retention'], errors='coerce').astype(np.float64) df['D30_retention'] = pd.to_numeric(df['D30_retention'], errors='coerce').astype(np.float64) # 결측치가 있는지 확인하고 제거 df = df.dropna(subset=['visit_days', 'D7_retention', 'D30_retention']) # 상수항 추가 X = sm.add_constant(df[['visit_days']]) # D7_retention에 대한 로지스틱 회귀 모델 적합 y_D7 = df['D7_retention'] logit_model_D7 = sm.Logit(y_D7, X).fit() print(logit_model_D7.summary()) # D30_retention에 대한 로지스틱 회귀 모델 적합 y_D30 = df['D30_retention'] logit_model_D30 = sm.Logit(y_D30, X).fit() print(logit_model_D30.summary())visit_days_range = np.linspace(df['visit_days'].min(), df['visit_days'].max(), 100) prob_D7 = logit_model_D7.predict(sm.add_constant(visit_days_range)) prob_D30 = logit_model_D30.predict(sm.add_constant(visit_days_range)) plt.plot(visit_days_range, prob_D7, label='D7 Retention Probability') plt.plot(visit_days_range, prob_D30, label='D30 Retention Probability', linestyle='--') plt.xlabel('Visit Days') plt.ylabel('Retention Probability') plt.title('Retention Probability vs Visit Days') plt.legend() plt.show()따라서, 방문일수는 Retention과 상관성을 보인다. 가설2. 방문일 수는 user_type에 따라 각기 다른 상관성을 보일 것이다.결론: user_type은 new_user, current_user는 통계적으로 유의하며, 높은 상관성을 가지나, 휴면 유저, 복귀 유저는 통계적으로 유의미하지 않으며, 낮은 상관성을 띈다. 이렇게 결론을 내놓는 방식이, 적합한 방식인지 궁금합니다.
-
미해결초보자를 위한 BigQuery(SQL) 입문
총 정리 문제 2번 쿼리 결과 질문
안녕하세요 카일스쿨님!총 정리 문제 2번의 쿼리 결과를 보고 문뜩 궁금증이 생겨 질문 남깁니다. 이렇게 쿼리를 짜서 카일스쿨님이 문제 풀이해주신 것처럼 같은 결과가 나왔습니다. 다만, 현재 GROUP BY가 타입1과 한글 이름 두 가지로 기준을 잡고 있어서저는 타입 1을 기준으로 가장 많은 포켓몬 수가 나올지, 아니면 한글이름 기준으로 가장 많은 포켓몬 수가 나올지 궁금해 했었는데, 한글 이름 기준으로 가장 많은 포켓몬 수가 나오더라구요!이러한 경우에는 왜 타입1과 한글 이름 두 가지가 다 기준으로 잡혀있는데, 타입1 기준이 아니라 한글 이름 기준으로 가장 많은 포켓몬 수가 출력되는 걸까요? 참고로 타입 1 기준으로 가장 많은 포켓몬 수를 구해봤더니 1순위는 Water로 나왔습니다.
-
해결됨초보자를 위한 BigQuery(SQL) 입문
JOIN 기준 질문
카일님, 안녕하세요! LEFT JOIN 기준이 헷갈려 이에 대한 질문 드립니다.LEFT JOIN 시 테이블의 데이터가 더 많은 테이블을 제일 왼쪽으로 두면 된다고 이해하면 될까요? 또한, 예외도 있다고 하셨는데, 어떤 경우인지도 알 수 있을까요?마지막으로 LEFT말고 다른 JOIN할 때도 테이블의 데이터가 더 많은 테이블을 기준으로 잡아도 괜찮나요?감사합니다!
-
해결됨초보자를 위한 BigQuery(SQL) 입문
2-5 where과 having 예시 쿼리문에 대한 질문
pdf파일 158페이지, 159페이지에 있는 where과 having 쿼리 예시문을 보다가 궁금한 게 생겨서요.where 쿼리문 : select 컬럼 1, 컬럼2라고 돼 있는데 group by 컬럼1, 컬럼2 라고 하지 않아도 실행이 가능한가요?having 쿼리문 : group by하는(그룹화 기준) 컬럼과 count 컬럼이 같을 수도 있나요? count (컬럼3)이어야 하지 않는지 궁금합니다!
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
리텐션 과제 연습문제 4번(core_event)
최근에, 면접이 있어서 공부를 제대로 못했네요. 오늘부터 매일 매일 못했던 공부를 다시 해보려고 합니다.문제: core_event를 'click_payment'라고 설정하고, Weekly Retention을 구하여라.저는 click_payment 까지의 사용자 여정 별로 세그먼트를 나누려는 시도를 해보았습니다. 문제에 대한 고민사항은 길어지니, 최종적으로 나누었던 세그먼트를 먼저 소개해드리겠습니다.click_payment 까지의 여정은 크게 다음과 같이 구성할 수 있습니다.click_search(검색) -> click_paymentclick_banner(배너 클릭) -> click_paymentclick_food_category(음식 카테고리 클릭) -> click_paymentclick_restaurant_nearby( 내 위치 기반 주변 레스토랑) -> click_paymentclick_recommend_food(추천) -> click_payment크게 다음과 같이 5개의 세그먼트로 나누어보고, 각 세그먼트 별로, Count를 해보았습니다. 이 때, click_login -> click_search -> .... -> click_payment -> click_search .... 이런 경우를 대비해서, 각 이벤트마다 제일 처음 이벤트가 발생한 시간 을 기준으로 구분하도록 하였습니다. 이제 각 퍼널별로 리텐션을 구해보겠습니다.WITH user_events AS ( SELECT user_pseudo_id, event_name, event_date, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_timestamp, ROW_NUMBER() OVER (PARTITION BY user_pseudo_id, event_name ORDER BY event_timestamp) AS r_num FROM advanced.app_logs WHERE event_name IN ('click_search', 'click_banner', 'click_food_category', 'click_restaurant_nearby', 'click_recommend_food', 'click_payment') AND event_name NOT IN ('screen_view', 'click_login') ), FIRST_EVENTS AS ( SELECT *, DATE_DIFF(event_week, first_week, WEEK) AS diff_of_week FROM ( SELECT user_pseudo_id, event_date, DATE_TRUNC(MIN(event_date) OVER (PARTITION BY user_pseudo_id), WEEK(MONDAY)) AS first_week, DATE_TRUNC(event_date, WEEK(MONDAY)) AS event_week, MIN(CASE WHEN event_name = 'click_search' THEN event_timestamp END) OVER (PARTITION BY user_pseudo_id, event_date) AS first_search_time, MIN(CASE WHEN event_name = 'click_payment' THEN event_timestamp END) OVER (PARTITION BY user_pseudo_id, event_date) AS first_payment_time, MIN(CASE WHEN event_name = 'click_banner' THEN event_timestamp END) OVER (PARTITION BY user_pseudo_id, event_date) AS first_banner_time, MIN(CASE WHEN event_name = 'click_food_category' THEN event_timestamp END) OVER (PARTITION BY user_pseudo_id, event_date) AS first_food_category_time, MIN(CASE WHEN event_name = 'click_restaurant_nearby' THEN event_timestamp END) OVER (PARTITION BY user_pseudo_id, event_date) AS first_restaurant_nearby_time, MIN(CASE WHEN event_name = 'click_recommend_food' THEN event_timestamp END) OVER (PARTITION BY user_pseudo_id, event_date) AS first_recommend_food_time FROM user_events ) ), FUNNEL_CLASSIFICATION AS ( SELECT DISTINCT *, CASE WHEN first_search_time IS NOT NULL AND first_payment_time IS NOT NULL AND first_search_time < first_payment_time THEN 'click_search -> click_payment' WHEN first_banner_time IS NOT NULL AND first_payment_time IS NOT NULL AND first_banner_time < first_payment_time THEN 'click_banner -> click_payment' WHEN first_food_category_time IS NOT NULL AND first_payment_time IS NOT NULL AND first_food_category_time < first_payment_time THEN 'click_food_category -> click_payment' WHEN first_restaurant_nearby_time IS NOT NULL AND first_payment_time IS NOT NULL AND first_restaurant_nearby_time < first_payment_time THEN 'click_restaurant_nearby -> click_payment' WHEN first_recommend_food_time IS NOT NULL AND first_payment_time IS NOT NULL AND first_recommend_food_time < first_payment_time THEN 'click_recommend_food -> click_payment' ELSE 'Other' END AS funnel FROM FIRST_EVENTS WHERE first_payment_time IS NOT NULL ), PIVOTED_ANALYSIS AS ( SELECT diff_of_week, COUNT(DISTINCT CASE WHEN funnel = 'click_search -> click_payment' THEN user_pseudo_id END) AS user_cnt_search_payment, COUNT(DISTINCT CASE WHEN funnel = 'click_banner -> click_payment' THEN user_pseudo_id END) AS user_cnt_banner_payment, COUNT(DISTINCT CASE WHEN funnel = 'click_food_category -> click_payment' THEN user_pseudo_id END) AS user_cnt_food_category_payment, COUNT(DISTINCT CASE WHEN funnel = 'click_restaurant_nearby -> click_payment' THEN user_pseudo_id END) AS user_cnt_restaurant_nearby_payment, COUNT(DISTINCT CASE WHEN funnel = 'click_recommend_food -> click_payment' THEN user_pseudo_id END) AS user_cnt_recommend_food_payment FROM FUNNEL_CLASSIFICATION GROUP BY diff_of_week ), INITIAL_USERS AS ( SELECT FIRST_VALUE(user_cnt_search_payment) OVER (ORDER BY diff_of_week) AS first_user_cnt_search_payment, FIRST_VALUE(user_cnt_banner_payment) OVER (ORDER BY diff_of_week) AS first_user_cnt_banner_payment, FIRST_VALUE(user_cnt_food_category_payment) OVER (ORDER BY diff_of_week) AS first_user_cnt_food_category_payment, FIRST_VALUE(user_cnt_restaurant_nearby_payment) OVER (ORDER BY diff_of_week) AS first_user_cnt_restaurant_nearby_payment, FIRST_VALUE(user_cnt_recommend_food_payment) OVER (ORDER BY diff_of_week) AS first_user_cnt_recommend_food_payment FROM PIVOTED_ANALYSIS LIMIT 1 ) SELECT pa.diff_of_week, pa.user_cnt_search_payment AS search_active_user, pa.user_cnt_banner_payment AS banner_active_user, pa.user_cnt_food_category_payment AS category_active_user, pa.user_cnt_restaurant_nearby_payment AS nearby_active_user, pa.user_cnt_recommend_food_payment AS recommend_active_user, iu.first_user_cnt_search_payment AS search_cohort_user, iu.first_user_cnt_banner_payment AS banner_cohort_user, iu.first_user_cnt_food_category_payment AS category_cohort_user, iu.first_user_cnt_restaurant_nearby_payment AS nearby_cohort_user, iu.first_user_cnt_recommend_food_payment AS recommend_cohort_user, ROUND(SAFE_DIVIDE(pa.user_cnt_search_payment, iu.first_user_cnt_search_payment), 3) AS retention_week_rate_search_payment, ROUND(SAFE_DIVIDE(pa.user_cnt_banner_payment, iu.first_user_cnt_banner_payment), 3) AS retention_week_rate_banner_payment, ROUND(SAFE_DIVIDE(pa.user_cnt_food_category_payment, iu.first_user_cnt_food_category_payment), 3) AS retention_week_rate_food_category_payment, ROUND(SAFE_DIVIDE(pa.user_cnt_restaurant_nearby_payment, iu.first_user_cnt_restaurant_nearby_payment), 3) AS retention_week_rate_restaurant_nearby_payment, ROUND(SAFE_DIVIDE(pa.user_cnt_recommend_food_payment, iu.first_user_cnt_recommend_food_payment), 3) AS retention_week_rate_recommend_food_payment FROM PIVOTED_ANALYSIS pa, INITIAL_USERS iu ORDER BY pa.diff_of_week; 1000자 이내로 작성해야 게시글 하나를 쓸 수 있음..screen_view -> screen_view -> click_login의 경우, 사용자가 로그인을 하지 않고, 앱이 잠시 백그라운드 상에 동작중인 상태에서, 다시 앱을 켰을 때, screen_view 로그가 찍히는 것을 확인했습니다.현재 집중해야 할 부분은 사용자가 상품을 들여다보는 시간이나, item을 찾을 때, UI/UX 적으로 개선할 부분이 있는지 찾기보다, click_payment를 하기까지의 주요 이벤트 여정을 세그먼트로 분류하는 작업을 하고 있기 때문에, screen_view 이벤트는 제외해야겠다는 생각을 했습니다.또한, screen_view -> click_login -> screen_view -> screen_view -> click_login 처럼, 이전 이벤트와 현재 이벤트가 같은 경우를 제외한 다른 경우만을 필터링해서, 굵직한 이벤트만을 필터링해보자! 라는 생각을 가졌었습니다.--- 1000자 이내로 작성해야 글이 올ㅠ 퍼널의 수가 열 몇개로 나오지 않을까? 하는 예상과 다르게 총 433개의 단계가 나왔습니다. click_login -> click_food_category -> click_restaurant -> click_food -> click_cart -> view_recommend_extra_food -> click_payment와 같이 click_login ----- > click_payment까지의 여정의 가짓수가 너무 많아, 단계를 단순화할 필요성이 있어보였습니다. 그래서, 위의 결과와 같이 총 5개로 퍼널을 나누었습니다.
-
해결됨초보자를 위한 BigQuery(SQL) 입문
5-6 1번 문제 풀이법
안녕하세요 카일스쿨님!5-1번 문제를 아래와 같이 SQL을 작성해 풀어보았는데요.답이 나오질 않았습니다.혹시 해당 쿼리에 어떤 문제가 있어 답이 나오지 않았을지 여쭤봅니다.감사합니다!
-
해결됨초보자를 위한 BigQuery(SQL) 입문
Bigquery내 SQL의 상호범용성 질문!
안녕하세요 카일스쿨님!카일스쿨님께서 만들어주신 해당 교육 너무 너무 잘 듣고 있습니다.설명도 알기 쉽게 너무 잘 해주시고, 이론적으로 배웠던 부분 실무에서도 사용할 수 있도록 예제 출제와 풀이도 같이 해주셔서 정말 탄탄하게 학습하고 있는 것 같습니다.다만, 제가 공부하면서 궁금한 지점이 있어 이렇게 질문 글을 남깁니다.저는 SQL공부를 위해서 해당 강의를 시청하고 있는데요!혹시 빅쿼리에서 사용하는 SQL문법이나 SQL작성방법이 MYSQL이나 ORACLE에서는 많이 다를까요?아니면 서로 범용할 수 있을까요?SQL 공부를 하기 위해 해당 강의를 듣고 있는데, 혹시나 빅쿼리에 한정된 공부를 하고 있는지 궁금해서 질문 남깁니다.좋은 강의자료와 강의, 그리고 질문에 대한 빠른 답변 항상 정말 감사합니다.날씨 더운데 건강 조심하시고, 저도 빠르게 기본강의 듣고 활용으로 넘어가고 싶습니다!감사합니다!
-
해결됨초보자를 위한 BigQuery(SQL) 입문
base.yml 파일까지는 찾았는데, 이후에 막혔어요
파일을 찾은 후에 편집을 하려고 더블 클릭을 하는데, 열 수 있는(?) 방법을 모르겠습니다. 뭔가를 따로 더 설치해야하나요?
-
해결됨초보자를 위한 BigQuery(SQL) 입문
Espanso 설치 후 터미널에서 편집 후 저장이 안됩니다(ESC :wq가 안먹어요.)
현재 이렇게까지 입력해놓은 상태인데,이 이후 ESC :wq가 인식이 안되고 ESC 누르고 콜론을 입력하면 에러 사운드가 뜨면서 밑에 Unknown Command 라는 안내 메시지가 뜹니다.어떻게 저장을 할 수 있을까요??