묻고 답해요
143만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 1주차 과제] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습 문제
ARRAY, STRUCT 연습문제-- 1. array_exercises 테이블에서 title 별로 genres를 UNNEST하기 SELECT title , genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) as genre; -- 2. array_exercises 테이블에서 title 별로 actor, character 추출 -- actor, character는 별도의 컬럼으로 빼기 (struct의 key로써 존재하면 안 됨.) SELECT title , ACTORS.actor AS actor , ACTORS.character AS character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS ACTORS; -- 3. array_exercises 테이블에서 title 별로 actor, character, genre 추출 -- 여러 ARRAY 컬럼을 UNNEST할 경우, 각 컬럼별로 UNNEST한 것을 CROSS JOIN 진행하면 됨. SELECT title , ACTORS.actor AS actor , ACTORS.character AS character , genre FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS ACTORS CROSS JOIN UNNEST(genres) as genre; -- 4. app_logs 테이블(약 73만 건의 로그 데이터)의 ARRAY를 UNNEST 하기 -- event_params 형태? -- ARRAY<STRUCT<key STRING, value STRUCT<string_value STRING, int_value INT64>>>[ -- STRUCT('firebase_screen', STRUCT('food_detail', NULL)) -- , ... -- ] SELECT user_id , event_date , event_name , user_pseudo_id , EVENT_PARAMS.key AS key , EVENT_PARAMS.value.string_value AS string_value , EVENT_PARAMS.value.int_value AS int_value FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS EVENT_PARAMS PIVOT 연습문제-- 1. orders 테이블에서 order_date별 user_id간 amount 합계를 PIVOT하기 SELECT order_date , SUM(IF(user_id=1, amount, 0)) AS user_1 , SUM(IF(user_id=2, amount, 0)) AS user_2 , SUM(IF(user_id=3, amount, 0))AS user_3 FROM advanced.orders GROUP BY order_date ORDER BY order_date ASC; -- 2. orders 테이블에서 user_id별 order_date 간 amount 합계를 PIVOT하기 SELECT user_id , SUM(IF(order_date='2023-05-01', amount, 0)) AS `2023-05-01` , SUM(IF(order_date='2023-05-02', amount, 0)) AS `2023-05-02` , SUM(IF(order_date='2023-05-03', amount, 0)) AS `2023-05-03` , SUM(IF(order_date='2023-05-04', amount, 0)) AS `2023-05-04` , SUM(IF(order_date='2023-05-05', amount, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY user_id ORDER BY user_id ASC; -- 3. orders 테이블에서 user_id별 order_date간 주문존재 여부 PIVOT하기 -- 주문 존재하면 1, 없으면 0; 주문횟수가 아님에 유의 SELECT user_id , MAX(IF(order_date='2023-05-01', 1, 0)) AS `2023-05-01` , MAX(IF(order_date='2023-05-02', 1, 0)) AS `2023-05-02` , MAX(IF(order_date='2023-05-03', 1, 0)) AS `2023-05-03` , MAX(IF(order_date='2023-05-04', 1, 0)) AS `2023-05-04` , MAX(IF(order_date='2023-05-05', 1, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY user_id ORDER BY user_id ASC; -- 4. app_logs 테이블 PIVOT 하기 -- user_id=32888이 카트 추가하기(click_cart)를 누를 때 어떤 음식(food_id)를 담았나요? WITH temp AS( SELECT user_id , event_date , event_name , event_timestamp , user_pseudo_id , EVENT_PARAMS.key AS key , EVENT_PARAMS.value.string_value AS string_value , EVENT_PARAMS.value.int_value AS int_value FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS EVENT_PARAMS ) SELECT user_id , event_date , event_name , event_timestamp , user_pseudo_id , MAX(IF(key='firebase_screen', string_value, null)) AS `firebase_screen` , MAX(IF(key='food_id', int_value, null)) AS `food_id` , MAX(IF(key='session_id', string_value, null)) AS `session_id` FROM temp -- GROUP BY user_id, event_date, event_timestamp, event_name, user_pseudo_id GROUP BY ALL 퍼널 쿼리 연습문제WITH main AS ( SELECT event_date, CONCAT(event_name,'-', event_param.value.string_value) AS event_name_with_screen, CASE WHEN event_name = 'screen_view' AND event_param.value.string_value = 'welcome' THEN 1 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'home' THEN 2 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'food_category' THEN 3 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'restaurant' THEN 4 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'cart' THEN 5 WHEN event_name = 'click_payment' AND event_param.value.string_value = 'cart' THEN 6 END AS step_num, COUNT(DISTINCT user_pseudo_id) AS cnt FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS event_param WHERE 1=1 AND event_date BETWEEN '2022-08-01' AND '2022-08-18' AND event_param.key = 'firebase_screen' AND event_name IN ("screen_view",'click_payment') GROUP BY 1,2,3 HAVING step_num IS NOT NULL ) SELECT event_date, SUM(IF(step_num = 1, cnt, 0)) AS `screen_view-welcome`, SUM(IF(step_num = 2, cnt, 0)) AS `screen_view-home`, SUM(IF(step_num = 3, cnt, 0)) AS `screen_view-food_category`, SUM(IF(step_num = 4, cnt, 0)) AS `screen_view-restaurant`, SUM(IF(step_num = 5, cnt, 0)) AS `screen_view-cart`, SUM(IF(step_num = 6, cnt, 0)) AS `click_payment-cart` FROM main GROUP BY 1 ORDER BY event_date ASC
-
해결됨[왕초보편] 앱 8개를 만들면서 배우는 안드로이드 코틀린(Android Kotlin)
리스트 뷰 질문 드립니다.
package com.jinyoung.myapplication import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter class ListViewAdapter(var List : MutableList<String>) : BaseAdapter() { override fun getCount(): Int { return List.size } override fun getItem(p0: Int): Any { return List[p0] } override fun getItemId(p0: Int): Long { TODO("Not yet implemented") } override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View { TODO("Not yet implemented") } }이 코드에서 3번째 함수 getItemId 함수의 return 값이 List[p0].toLong()이 되어야하는거 아닌가요????
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 1주차 과제] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습 문제
SELECT [1, 2, 3, 4, 5] AS some_numbers ; SELECT ARRAY<INT64>[1, 2, 3, 4, 5] AS some_numbers ; SELECT GENERATE_ARRAY(1, 5, 1) AS some_numbers ; SELECT [SAFE_OFFSET()] ; SELECT (1, 2, 3) AS struct_test ; SELECT STRUCT<hi INT64, hello INT64>(1, 2) AS struct_test ;SELECT a.title, b AS genre FROM workspace.array_exercises AS a JOIN UNNEST(genres) AS b ; SELECT a.title, b.actor, b.character FROM workspace.array_exercises AS a JOIN UNNEST(actors) AS b ; SELECT a.title, b.actor, b.character, c AS genre FROM workspace.array_exercises AS a JOIN UNNEST(actors) AS b JOIN UNNEST(genres) AS c ; SELECT a.user_id, a.event_date, a.event_name, a.user_pseudo_id, b.key, b.value.string_value, b.value.int_value FROM workspace.app_logs AS a JOIN UNNEST(event_params) AS b ; SELECT key, string_value, count(distinct user_pseudo_id) FROM ( SELECT a.user_id, a.event_date, a.event_name, a.user_pseudo_id, b.key, b.value.string_value, b.value.int_value FROM workspace.app_logs AS a JOIN UNNEST(event_params) AS b ) WHERE event_name = 'screen_view' GROUP BY ALL ; SELECT order_date, sum(if(user_id = 1, amount, 0)) as user_1, sum(if(user_id = 2, amount, 0)) as user_2, sum(if(user_id = 3, amount, 0)) as user_3 FROM workspace.orders GROUP BY ALL ORDER BY order_date ; SELECT user_id, sum(if(order_date = '2023-05-01', amount, 0)) `2023-05-01`, sum(if(order_date = '2023-05-02', amount, 0)) `2023-05-02`, sum(if(order_date = '2023-05-03', amount, 0)) `2023-05-03`, sum(if(order_date = '2023-05-04', amount, 0)) `2023-05-04`, sum(if(order_date = '2023-05-05', amount, 0)) `2023-05-05` FROM workspace.orders GROUP BY ALL ORDER BY user_id ; SELECT user_id, if(sum(if(order_date = '2023-05-01', amount, 0)) > 0, 1, 0) `2023-05-01`, if(sum(if(order_date = '2023-05-02', amount, 0)) > 0, 1, 0) `2023-05-02`, if(sum(if(order_date = '2023-05-03', amount, 0)) > 0, 1, 0) `2023-05-03`, if(sum(if(order_date = '2023-05-04', amount, 0)) > 0, 1, 0) `2023-05-04`, if(sum(if(order_date = '2023-05-05', amount, 0)) > 0, 1, 0) `2023-05-05` FROM workspace.orders GROUP BY ALL ORDER BY user_id ; WITH events AS ( SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, platform, MAX(IF(b.key = "firebase_screen", b.value.string_value, NULL)) AS firebase_screen, MAX(IF(b.key = "session_id", b.value.string_value, NULL)) AS session_id FROM workspace.app_logs AS a JOIN UNNEST(event_params) AS b WHERE event_date >= '2022-08-01' AND event_date < '2022-08-19' GROUP BY ALL ), filter_event_and_concat_event_and_screen AS ( SELECT * EXCEPT(event_name, firebase_screen, event_timestamp), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM events WHERE event_name IN ('screen_view', 'click_payment') ) SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = 'screen_view-welcome' THEN 1 WHEN event_name_with_screen = 'screen_view-home' THEN 2 WHEN event_name_with_screen = 'screen_view-food_category' THEN 3 WHEN event_name_with_screen = 'screen_view-restaurant' THEN 4 WHEN event_name_with_screen = 'screen_view-cart' THEN 5 WHEN event_name_with_screen = 'click_payment-cart' THEN 6 END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM filter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL ;
-
해결됨Part2: 초중급 iOS 인스타그램 클론(SwiftUI, MVVM, Firebase, 2024)
혹시 다음 강의 대략 언제쯤 완료되시는지 알 수 있을까요??
안녕하세요, 강의 정말 인상깊게 봤습니다!! 다른 글에서 다음 강의로 Combine 관련 내용으로 제작중이라고 하셨는데, 대략 언제쯤 다음 강의 제작이 끝나시는지 궁금하여 이렇게 글을 남깁니다. 강의 나오면 바로 구매할 예정입니다! 감사합니다.
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 1주차 과제] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습 문제
ARRAY, STRUCT 연습문제-- 1)영화별 장르를 unnest해서 보여줘라. SELECT title, genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) AS genre; --2) 영화별 배우와 배역을 보여줘라. 배우와 배역은 별도의 컬럼으로 나와야 한다. SELECT title, ac.actor, ac.character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS ac; --3. 영화별로 배우, 배역, 장르를 출력해라. SELECT title, actor.actor, actor.character, genre FROM `advanced.array_exercises` CROSS JOIN UNNEST(actors) as actor CROSS JOIN UNNEST(genres) as genre; --4. 앱 로그 데이터의 배열을 풀어라 SELECT user_id, event_date, event_name, user_pseudo_id, event_param.key, event_param.value.string_value, event_param.value.int_value FROM `advanced.app_logs` CROSS JOIN UNNEST(event_params) AS event_param PIVOT 연습문제-- 1. 유저별 주문금액의 합계를 poviot해라. -- SELECT -- order_date, -- SUM(IF(user_id = 1, amount, 0)) AS user_1, -- SUM(IF(user_id = 2, amount, 0)) AS user_2, -- SUM(IF(user_id = 3, amount, 0)) AS user_3 -- FROM `advanced.orders` -- GROUP BY order_date -- ORDER BY order_date; -- 2. 날짜별 유저들의 주문금액의 합계를 pivot해라. -- SELECT -- user_id, -- SUM(IF(order_date = '2023-05-01', amount, 0)) AS `2023-05-01`, -- SUM(IF(order_date = '2023-05-02', amount, 0)) AS `2023-05-02`, -- SUM(IF(order_date = '2023-05-03', amount, 0)) AS `2023-05-03`, -- SUM(IF(order_date = '2023-05-04', amount, 0)) AS `2023-05-04`, -- SUM(IF(order_date = '2023-05-05', amount, 0)) AS `2023-05-05` -- FROM advanced.orders -- GROUP BY user_id -- ORDER BY user_id; -- 3. 사용자별, 날짜별 주문이 있다면 1, 없다면 0으로 pivot해라. -- SELECT -- user_id, -- MAX(IF(order_date = '2023-05-01', 1, 0)) AS `2023-05-01`, -- MAX(IF(order_date = '2023-05-02', 1, 0)) AS `2023-05-02`, -- MAX(IF(order_date = '2023-05-03', 1, 0)) AS `2023-05-03`, -- MAX(IF(order_date = '2023-05-04', 1, 0)) AS `2023-05-04`, -- MAX(IF(order_date = '2023-05-05', 1, 0)) AS `2023-05-05` -- FROM advanced.orders -- GROUP BY user_id -- ORDER BY user_id; --4. key값을 column으로 pivot해라 SELECT user_id, event_date, event_name, user_pseudo_id, IF(key = 'food_id', IF(string_value IS NOT NULL, string_value, CAST(int_value AS STRING)), NULL) AS food_id FROM advanced.app_logs_unnest # app_logs 테이블을 unnest한 결과는 자주 쓰일 듯 싶어 app_logs_unnest 테이블을 따로 생성했다. WHERE event_name = 'click_cart' AND event_date = '2022-08-01'; 기억할 것IF 조건문을 사용할 때, TRUE일때의 값과 FALSE일때의 값의 데이터 타입이 같아야 한다. PIVOT 연습문제 4번을 풀 때 food_id를 PIVOT하는 과정에서 IF(key = 'food_id', IF(string_value IS NOT NULL, string_value, int_value AS STRING), NULL)와 같이 표현했었다. KEY값에 따라 string_value와 int_value중 타입에 맞는 하나의 컬럼에만 값이 있었고, 처음에는 이를 명시적으로 적기보다 범용적으로 사용될 수 있도록 하는게 더 좋지 않을까 싶었다. 값이 있는 컬럼의 값을 사용하자는 의도로 IF(string_value IS NOT NULL, string_value, int_value AS STRING)라고 표현했고 다음과 같은 에러를 만났다.No matching signature for function IF for argument types: BOOL, STRING, INT64. Supported signature: IF(BOOL, ANY, ANY) at [55:23]에러를 피하고자 CAST를 이용했는데 데이터 타입을 억지로 바꾸기보다는(추후에 숫자형 데이터로 대소 비교를 한다던지 나열을 한나던지의 상황이 있을 수 있으니..) 명시적으로 표현하는 것을 마냥 피할것은 아니겠다는 생각을 했다.특별한 문자(예약어, 숫자)를 ALIAS로 설정하려면 back tick(`)으로 감싸줘야한다.퍼널 쿼리 연습문제-- 퍼널 별 유저 수 집계(2022-08-01 ~ 2022-08-18) -- welcome -> home -> good category -> restaurant -> cart -> 주문하기 클릭 /* event_data | event_name_with_screen | stemp_number | cnt 의 컬럼 형태로 만들것 */ -- 처음 작성했던 쿼리 -- SELECT -- event_date, -- CASE -- WHEN event_name = 'screen_view' AND string_value = 'welcome' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'home' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'food_category' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'restaurant' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'cart' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'click_payment' AND string_value = 'cart' THEN CONCAT(event_name, '-', string_value) -- END AS event_name_with_screen, -- CASE -- WHEN event_name = 'screen_view' AND string_value = 'welcome' THEN 1 -- WHEN event_name = 'screen_view' AND string_value = 'home' THEN 2 -- WHEN event_name = 'screen_view' AND string_value = 'food_category' THEN 3 -- WHEN event_name = 'screen_view' AND string_value = 'restaurant' THEN 4 -- WHEN event_name = 'screen_view' AND string_value = 'cart' THEN 5 -- WHEN event_name = 'click_payment' AND string_value = 'cart' THEN 6 -- END AS step_number, -- COUNT(event_date) AS cnt -- FROM `advanced.app_logs_unnest` -- WHERE -- event_date BETWEEN '2022-08-01' AND '2022-08-18' -- GROUP BY ALL -- ORDER BY event_date, step_number -- ============================================= -- 정석 쿼리 WITH base AS( SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, platform, MAX(IF(event_param.key = "firebase_screen", event_param.value.string_value, NULL)) AS firebase_screen, MAX(IF(event_param.key = "food_id", event_param.value.int_value, NULL)) AS food_id, MAX(IF(event_param.key = "session_id", event_param.value.int_value, NULL)) AS session_id FROM `advanced.app_logs` CROSS JOIN UNNEST(event_params) AS event_param -- WHERE -- event_date = "2022-08-01" -- event_date BETWEEN "2022-08-01" AND "2022-08-18" -- AND -- event_param.key IN ("screen_view", "click_payment") -- AND -- event_param.value.string_value IN ("welcome", "home", "food_category", "restaurant", "cart") GROUP BY ALL ), filter_event_and_concat_event_and_screen AS( SELECT * EXCEPT(event_name, firebase_screen), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), "Asia/Seoul") AS event_datetime FROM base WHERE event_date BETWEEN "2022-08-01" AND "2022-08-18" AND event_name IN ("screen_view", "click_payment") AND firebase_screen IN ("welcome", "home", "food_category", "restaurant", "cart") ) SELECT event_date, event_name_with_screen, -- event_datetime, -- user_pseudo_id, CASE WHEN event_name_with_screen = 'screen_view-welcome' THEN 1 WHEN event_name_with_screen = 'screen_view-home' THEN 2 WHEN event_name_with_screen = 'screen_view-food_category' THEN 3 WHEN event_name_with_screen = 'screen_view-restaurant' THEN 4 WHEN event_name_with_screen = 'screen_view-cart' THEN 5 WHEN event_name_with_screen = 'click_payment-cart' THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM filter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL ORDER BY event_date, step_number기억할 것각 컬럼에 어떤 값이 있는지 잘! 확인하자.event_name_with_screen 부분을 CASE WHEN으로 처리하며 '이게 진정 맞을까......' 싶긴 했었었다. 왜인지 초반에 컬럼값 확인할 때 WHERE 절에 IN 구문으로 확인했을때 원하던 결과로 나오지 않아 CASE WHEN으로 직접 처리했었는데.. 실수였다. (아마 string_value만 IN연산으로 확인하고 섣부른 판단을 했던게 아닐지 싶다.)CASE WHEN 구문에서 전체를 포함하도록 조건을 구성하지 않으면 WHEN에 해당하지 않는 부분은 NULL값으로 생성된다.처음 쿼리를 짜고 CNT 컬럼의 값을 확인했을 때 event_name_with_screen과 step_number에 왜 NULL값이 있는지 당황스러웠다. 이미 있는 데이터에 새 컬럼을 만든 것이니 조건에 해당되지 않는 부분은 값이 없어 NULL로 남아있다는 사실...!DATETIME 함수를 이용하여 "Asia/Seoul" 처리하기새까맣게 잊고있었다. 까먹지 말자~!항상 데이터를 뽑아 어떤 내용을 확인하고 싶은 건지를 생각하자.문제에 맞는 쿼리를 짜고 작성된 쿼리의 결과가 잘 나오는지에만 급급했던 거 같다. 이 강의를 듣는 목적은 데이터 분석에 대한 감 잡기!지 쿼리 잘 짜기!는 아니었으니까..!(물론 SQL 실력 향상은 필요한 부분..!!) 스스로 고민해보는 시간을 꼭! 갖도록 해보자.
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 1주차 과제] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습 문제
1) ARRAY, STRUCT 연습문제1-1)SELECT title, genre FROM advanced.array_exercises CROSS JOIN UNNEST (genres) as genre ORDER BY title;1-2)SELECT title, actor.actor, actor.character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) as actor ORDER BY title;1-3)SELECT title, actor.actor, actor.character, genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) as genre CROSS JOIN UNNEST(actors) as actor ORDER BY 1,2,3;1-4)SELECT user_id, event_date, event_name, user_pseudo_id, event_param.key, event_param.value.string_value, event_param.value.int_value FROM advanced.app_logs CROSS JOIN UNNEST(event_params) as event_param WHERE event_date = '2022-08-01';2) PIVOT 연습문제2-1) 1) SELECT order_date, SUM(IF(user_id = 1, amount, 0 )) AS user_1, SUM(IF(user_id = 2, amount, 0 )) AS user_2, SUM(IF(user_id = 3, amount, 0 )) AS user_3 FROM advanced.orders GROUP BY 1 ORDER BY 1;2-2)SELECT user_id, SUM(IF(order_date = '2023-05-01', amount, 0)) AS `2023-05-01`, SUM(IF(order_date = '2023-05-02', amount, 0)) AS `2023-05-02`, SUM(IF(order_date = '2023-05-03', amount, 0)) AS `2023-05-03`, SUM(IF(order_date = '2023-05-04', amount, 0)) AS `2023-05-04`, SUM(IF(order_date = '2023-05-05', amount, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY 1 ORDER BY 1;2-3)SELECT user_id, MAX(IF(order_date = '2023-05-01', 1, 0)) AS `2023-05-01`, MAX(IF(order_date = '2023-05-02', 1, 0)) AS `2023-05-02`, MAX(IF(order_date = '2023-05-03', 1, 0)) AS `2023-05-03`, MAX(IF(order_date = '2023-05-04', 1, 0)) AS `2023-05-04`, MAX(IF(order_date = '2023-05-05', 1, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY 1 ORDER BY 1;2-4)SELECT event_date, event_timestamp, event_name, event_timestamp, user_pseudo_id, MAX(CASE WHEN event_param.key = 'firebase_screen' THEN event_param.value.string_value END) as firebase_screen, MAX(CASE WHEN event_param.key = 'food_id' THEN event_param.value.int_value END) as food_id, MAX(CASE WHEN event_param.key = 'session_id' THEN event_param.value.string_value END) as session_id, FROM advanced.app_logs CROSS JOIN UNNEST(event_params) as event_param WHERE event_date = '2022-08-01' GROUP BY ALL 3) 퍼널 쿼리 연습 문제WITH main as ( SELECT event_date, concat(event_name,'-', event_param.value.string_value) AS event_name_with_screen, CASE WHEN event_name = 'screen_view' AND event_param.value.string_value = 'welcome' THEN 1 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'home' THEN 2 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'food_category' THEN 3 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'restaurant' THEN 4 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'cart' THEN 5 WHEN event_name = 'click_payment' AND event_param.value.string_value = 'cart' THEN 6 END AS step_num, count(distinct user_pseudo_id) AS cnt FROM advanced.app_logs CROSS JOIN UNNEST(event_params) as event_param WHERE event_date between '2022-08-01' AND '2022-08-18' AND event_param.key = 'firebase_screen' AND event_name IN ("screen_view",'click_payment') GROUP BY 1,2,3 HAVING step_num IS NOT NULL ) SELECT event_date, SUM(IF(step_num = 1, cnt, 0)) AS `screen_view-welcome`, SUM(IF(step_num = 2, cnt, 0)) AS `screen_view-home`, SUM(IF(step_num = 3, cnt, 0)) AS `screen_view-food_category`, SUM(IF(step_num = 4, cnt, 0)) AS `screen_view-restaurant`, SUM(IF(step_num = 5, cnt, 0)) AS `screen_view-cart`, SUM(IF(step_num = 6, cnt, 0)) AS `click_payment-cart` FROM main GROUP BY 1 ORDER BY event_date
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[인프런 빅쿼리 빠짝스터디 1주차] ARRAY, STRUCT, PIVOT,퍼널 쿼리
연습 문제(1) Array, Struct-- 1) array_exercises 테이블에서 각 영화(title)별로 장르(genres)를 UNNEST해서 보여주세요 SELECT title, genre # genres 아님 FROM `advanced.array_exercises` CROSS JOIN UNNEST(genres) AS genre처음에 'title'을 기준으로 묶여 있길래 UNNEST의 요소로 'title'을 넣으려 함 → ERROR생각해보니 CROSS JOIN이 목적이므로 개별 값을 가지는 'genres'를 기준으로 UNNEST-- 2) array_exercises 테이블에서 각 영화(title)별로 배우(actor)와 배역(character)을 보여주세요. 배우와 배역은 별도의 컬럼으로 나와야 합니다 SELECT title, actor, character FROM `advanced.array_exercises`, UNNEST(actors)CROSS JOIN 대신 ','를 통해 UNNEST를 시도해 봄 -- 3) array_exercises 테이블에서 각 영화(title)별로 배우(actor), 배역(character), 장르 (genre)를 출력하세요. -- 한 Row에 배우, 배역, 장르가 모두 표시되어야 합니다 SELECT title, ae2.actor, ae2.character, genre FROM ( SELECT title, actor.actor, actor.character, genres FROM `advanced.array_exercises` AS ae, UNNEST(actors) AS actor ) AS ae2, UNNEST(genres) AS genre-- 강의 코드 SELECT title, actor.actor, actor.character, genre FROM `advanced.array_exercises` AS ae, UNNEST(actors) AS actor, UNNEST(genres) AS genreUNNEST 두번해야해서 서브쿼리로 해결하려 시도 → 서브 쿼리 안하고 UNNEST 두번 사용 가능실행 순서 : FROM → JOIN → SELECTcmd + D : 다음 해당 항목 같이 선택 → 반복되는 단어 쉽게 수정 가능-- 4) 앱 로그 데이터(app_logs)의 배열을 풀어주세요 SELECT user_id, event_date, event_name, user_pseudo_id, EV.key, EV.value.string_value, EV.value.int_value FROM `advanced.app_logs` AS al, UNNEST(event_params) AS EV-- 강의 코드 SELECT event_date, event_timestamp, event_name, event_param.key AS key, event_param.value AS value, user_id FROM `advanced.app_logs`, UNNEST(event_params) AS event_param WHERE event_date = "2022-08-01"WHERE에 조건을 넣어 연산량 낮출 수 있음event_params로 UNNEST했을때 value값만 사용해도 string, int 둘다 표시됨 (2) PIVOTparquet : 대용량 데이터를 효율적으로 저장하고 처리하기 위해 설계된 컬럼 기반의 저장 형식공통 사항 : 행과 열에 대한 정의가 한번에 떠오르지 않았음-- 1) orders 테이블에서 유저(user_id)별로 주문 금액(amount)의 합계를 PIVOT해주세요. -- 날짜(order_date)를 행(Row)으로, user_id를 열(Column)으로 만들어야 합니다 SELECT order_date, SUM(IF(user_id=1, amount, 0)) AS user_1, SUM(IF(user_id=2, amount, 0)) AS user_2, SUM(IF(user_id=3, amount, 0)) AS user_3, FROM `advanced.orders` GROUP BY order_date ORDER BY order_dateNULL과 0은 다르다서브쿼리 이용한 방법도 있음(집계 후 PIVOT)-- 2) orders 테이블에서 날짜(order_date)별로 유저들의 주문 금액(amount)의 합계를 PIVOT 해주세요. -- user_id를 행(Row)으로, order_date를 열(Column)으로 만들어야 합니다 SELECT user_id, SUM(IF(order_date="2023-05-01", amount, 0)) AS `2023-05-01`, SUM(IF(order_date="2023-05-02", amount, 0)) AS `2023-05-02`, SUM(IF(order_date="2023-05-03", amount, 0)) AS `2023-05-03`, SUM(IF(order_date="2023-05-04", amount, 0)) AS `2023-05-04`, SUM(IF(order_date="2023-05-05", amount, 0)) AS `2023-05-05`, FROM `advanced.orders` GROUP BY user_idAS에서 “ ”(따옴표) 대신 (백틱) 사용ANY_VALUE : 그룹화 할 대상 중에 임의의 값을 선택한다(NULL 제외) 따라서 나머지 값들이 NULL이거나 값이 확정적일 때 사용-- 3) orders 테이블에서 사용자(user_id)별, 날짜(order_date)별로 주문이 있다면 1, 없다면 0으로 PIVOT 해주세요. -- user_id를 행(Row)으로, order_date를 열(Column)로 만들고 주문을 많이 해도 1로 처리합니다 SELECT user_id, MAX(IF(order_date="2023-05-01", 1, 0)) AS `2023-05-01`, MAX(IF(order_date="2023-05-02", 1, 0)) AS `2023-05-02`, MAX(IF(order_date="2023-05-03", 1, 0)) AS `2023-05-03`, MAX(IF(order_date="2023-05-04", 1, 0)) AS `2023-05-04`, MAX(IF(order_date="2023-05-05", 1, 0)) AS `2023-05-05`, FROM `advanced.orders` GROUP BY user_id조건문에서 행 별로 주문 있으면 1, 없으면 0 설정한 뒤 MAX 조건 걸어줌 → 최종적으로 값이 있으면 1횟수일 경우에는 SUM-- user_id = 32888이 카트 추가하기(click_cart)를 누를때 어떤 음식(food_id)을 담았나요? => 쿼리 작성이 어려움 -- => key를 Column으로 두고, string_value나 int_value를 Column의 값으로 설정하는 것이 필요 SELECT user_id, event_date, event_name, event_timestamp, ANY_VALUE(IF(event_param.key="firebase_screen", event_param.value.string_value, NULL)) AS `firebase_screen`, ANY_VALUE(IF(event_param.key="food_id", event_param.value.int_value, NULL)) AS `food_id`, ANY_VALUE(IF(event_param.key="session_id", event_param.value.string_value, NULL)) AS `session_id`, FROM `advanced.app_logs`, UNNEST(event_params) AS event_param WHERE (event_date = "2022-08-01") AND (event_name = "click_cart") AND (user_id = 32888) # 선택 사항 GROUP BY user_id, event_date, event_name, event_timestamp문제를 봤을 때 문제가 원하는게 무엇인지 한번에 파악되지 않았음32888의 click cart 행위에만 집중하는 것으로 판단GROUP BY ALL 을 통해 한번에 해결 가능(3) 퍼널 쿼리WITH base AS ( SELECT user_id, user_pseudo_id, event_date, event_name, event_timestamp, platform, ANY_VALUE(IF(event_param.key="firebase_screen", event_param.value.string_value, NULL)) AS `firebase_screen`, ANY_VALUE(IF(event_param.key="food_id", event_param.value.int_value, NULL)) AS `food_id`, ANY_VALUE(IF(event_param.key="session_id", event_param.value.string_value, NULL)) AS `session_id`, FROM `advanced.app_logs`, UNNEST(event_params) AS event_param WHERE event_date BETWEEN "2022-08-01" AND "2022-08-18" GROUP BY ALL )event_name과 event_params가 연결되어야 하므로 우선 UNNEST 필요하다고 생각함 → 이전에 사용했던 쿼리문 그대로 사용 후 WITH하지만 이후 과정에서 CONCAT 함수를 떠올리지 못해 진행이 불가했음), concat_event_screen AS ( SELECT * EXCEPT(event_name, firebase_screen, event_timestamp), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM base )이후에 concat_event_screen이라는 이름으로 테이블 재가공 해줌CONCAT을 통해 event_name-firebase-screenevent_timestamp 알아보기 쉽게 바꿔준 후 제거SELECT event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM concat_event_screen GROUP BY ALL HAVING step_number IS NOT NULL # CASE-WHEN에서 포함되지 않는 행위는 제거CASE-WHEN 이용해서 step_number 컬럼 만들어줌COUNT + DISTINC 이용해 해당 퍼널에 진입한 고유 유저 수 세주기퍼널이 아직 익숙하지 않아 혼자서 해결할 수는 없었음+) 일자별SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM concat_event_screen GROUP BY ALL HAVING step_number IS NOT NULL # CASE-WHEN에서 포함되지 않는 행위는 제거 ORDER BY event_date간단한 EDA지금까지 배운 것을 바탕으로 간단한 데이터 탐색 및 분석행 개수 → 731873행2022-08-01(월) ~ 2023-01-20(금) 의 데이터user_id 고유 개수 → 49678pseudo_user_id 고유 개수 → 52823event_params → 22개아래 표는 전체 기간에 대한 각 event_params별 개수 총합(내림차순)-> 개수가 같은 항목들이 존재-> 앱 작동 흐름에 대해 알 필요 있어 보임event_date에 따른 pseudo_user_id 고유 개수 그래프-> 8월부터 10월 중순까지는 이용자수가 늘어나는 추세-> 이후 안정기 들어서면서 일정한 주기로 반복되는 형태느낀점보통 데이터 분석 프로젝트를 하면 Python이나 R을 통해 진행했기에 아직 쿼리문이 생소함머릿속으로는 대충 어떤 식으로 데이터를 건드려야겠다는 생각이 들긴 하지만, 표현이 잘 안되는 경우가 많아서 까다로웠던 것 같음업무 경험이 없는 입장에서 퍼널 분석 같은 것들은 실제로 해본적이 없는데, 비교적 이해하기 쉽게 알려주신 것 같음
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[인프런 빅쿼리 빠짝스터디 1주차] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습문제
연습문제(1) ARRAY, STRUCT-- 1) array_exercises 테이블에서 각 영화(title)별로 장르(genres)를 UNNEST해서 보여주세요 # 쿼리를 작성하는 목표, 확인할 지표 : 평면화 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : array_exercises # Join KEY : # 데이터 특징 : SELECT title, genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) AS genre; -- 2) array_exercises 테이블에서 각 영화(title)별로 배우(actor)와 배역(character)을 보여주세요. 배우와 배역은 별도의 컬럼으로 나와야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : 영화별 배우와 배역 평면화 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : array_exercises # Join KEY : # 데이터 특징 : 배우와 배역은 별도의 컬럼으로 나와야 합니다 SELECT title, actor.actor, actor.character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS actor; -- 3) array_exercises 테이블에서 각 영화(title)별로 배우(actor), 배역(character), 장르 (genre)를 출력하세요. 한 Row에 배우, 배역, 장르가 모두 표시되어야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : 배우, 배역, 장르 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : array_exercises # Join KEY : # 데이터 특징 : 한 Row에 배우, 배역, 장르가 모두 표시되어야 함 SELECT title, actor.actor, actor.character, genre FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS actor CROSS JOIN UNNEST(genres) AS genre; -- 4) 앱 로그 데이터(app_logs)의 배열을 풀어주세요 # 쿼리를 작성하는 목표, 확인할 지표 : 앱 로그 데이터 평면화 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : app_logs # Join KEY : # 데이터 특징 : event_params안에 ARRAY와 STRUCT 구조가 공존하고 있고 값이 string_value와 int_value 두 종류로 나뉨 확인 필요!! SELECT user_id, event_date, event_name, user_pseudo_id, event_param.key, event_param.value.string_value, event_param.value.int_value FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS event_param WHERE event_date = "2022-08-01";(2) PIVOT-- 1) orders 테이블에서 유저(user_id)별로 주문 금액(amount)의 합계를 PIVOT해주세요. 날짜(order_date)를 행(Row)으로, user_id를 열(Column)으로 만들어야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : # 쿼리 계산 방법 : MAX, IF, GROUP BY # 데이터의 기간 : # 사용할 테이블 : orders # Join KEY : # 데이터 특징 : SELECT order_date, SUM(IF(user_id = 1, amount, 0)) AS user_1, SUM(IF(user_id = 2, amount, 0)) AS user_2, SUM(IF(user_id = 3, amount, 0)) AS user_3, FROM advanced.orders GROUP BY ALL ORDER BY order_date; -- 2) orders 테이블에서 날짜(order_date)별로 유저들의 주문 금액(amount)의 합계를 PIVOT 해주세요. user_id를 행(Row)으로, order_date를 열(Column)으로 만들어야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : # 쿼리 계산 방법 : SUM, IF, GROUP BY # 데이터의 기간 : # 사용할 테이블 : orders # Join KEY : # 데이터 특징 : SELECT user_id, SUM(IF(order_date = "2023-05-01", amount, 0)) AS `2023-05-01`, SUM(IF(order_date = "2023-05-02", amount, 0)) AS `2023-05-02`, SUM(IF(order_date = "2023-05-03", amount, 0)) AS `2023-05-03`, SUM(IF(order_date = "2023-05-04", amount, 0)) AS `2023-05-04`, SUM(IF(order_date = "2023-05-05", amount, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY ALL ORDER BY user_id; -- 3) orders 테이블에서 사용자(user_id)별, 날짜(order_date)별로 주문이 있다면 1, 없다면 0으로 PIVOT 해주세요. user_id를 행(Row)으로, order_date를 열(Column)로 만들고 주문을 많이 해도 1로 처리합니다 # 쿼리를 작성하는 목표, 확인할 지표 : # 쿼리 계산 방법 : MAX, IF, GROUP BY # 데이터의 기간 : # 사용할 테이블 : orders # Join KEY : # 데이터 특징 : SELECT user_id, MAX(IF(order_date = "2023-05-01", 1, 0)) AS `2023-05-01`, MAX(IF(order_date = "2023-05-02", 1, 0)) AS `2023-05-02`, MAX(IF(order_date = "2023-05-03", 1, 0)) AS `2023-05-03`, MAX(IF(order_date = "2023-05-04", 1, 0)) AS `2023-05-04`, MAX(IF(order_date = "2023-05-05", 1, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY ALL ORDER BY user_id; -- 연습문제 4) app_log를 pivot하기 # 쿼리를 작성하는 목표, 확인할 지표 : app_log 데이터 PIVOT 테이블로 변경 # 쿼리 계산 방법 : UNNEST, MAX, IF, GROUP BY # 데이터의 기간 : 2022-08-01 # 사용할 테이블 : app_logs # Join KEY : # 데이터 특징 : event_params안에 ARRAY와 STRUCT 구조가 공존하고 있고 값이 string_value와 int_value 두 종류로 나뉨 확인 필요!! WITH base AS( SELECT user_id, event_date, event_name, event_timestamp, user_pseudo_id, MAX(if(event_param.key = "firebase_screen", event_param.value.string_value, NULL)) AS firebase_screen, MAX(if(event_param.key ="food_id", event_param.value.int_value, NULL)) AS food_id, MAX(if(event_param.key ="session_id", event_param.value.string_value, NULL)) AS session_id FROM avdanced.app_logs CROSS JOIN UNNEST (event_params) AS event_param WHERE event_date ='2022-08-01' GROUP BY ALL ) SELECT event_date, COUNT(user_id) AS cnt FROM base WHERE event_name = 'click_cart' GROUP BY ALL;(3) 퍼널 ( Funnel )# 쿼리를 작성하는 목표, 확인할 지표 : screen_view-welcome, screen_view-home, screen_view-food_category, screen_view-restaurant, screen_view-cart, click_payment-cart 순서대로 step_number를 지정하고 퍼널 분석하기 # 쿼리 계산 방법 : MAX, IF, UNNEST, CASE WHEN # 데이터의 기간 : 2022-08-01 ~ 2022-08-18 # 사용할 테이블 : app_logs # Join KEY : # 데이터 특징 : event_params안에 ARRAY와 STRUCT 구조가 공존하고 있고 값이 string_value와 int_value 두 종류로 나뉨 확인 필요!! WITH base AS (SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, platform, MAX(IF(event_param.key = "firebase_screen", event_param.value.string_value, NULL)) AS fire_screen, -- MAX(IF(event_param.key = "food_id", event_param.value.int_value, NULL)) AS food_id, MAX(IF(event_param.key = "session_id", event_param.value.string_value, NULL)) AS session_id FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS event_param WHERE event_date BETWEEN "2022-08-01" AND "2022-08-18" GROUP BY ALL ), fiter_event_and_concat_event_and_screen AS ( -- event_name + screen (필요한 이벤트만 WHERE 조건에 걸어서 사용) SELECT * EXCEPT(event_name, fire_screen, event_timestamp), CONCAT(event_name, "-", fire_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM base WHERE event_name IN ("screen_view", "click_payment") ) -- step_number + COUNT -- step_number : CASE WHEN을 사용해 숫자 지정 SELECT event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM fiter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL WHERE user_pseudo_id = "1350836585.3421064109" -- 일자별 SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM fiter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL ORDER BY event_date;배운점ARRAY와 STRUCT 라는 조금은 생소할 수 있는 데이터 타입과 이를 어떻게 하면 평면화로 풀고 어떻게 데이터를 처리할 수 있을지를 조금은 알 수 있었고BigQuery로 생각보다 많은 부분을 할 수 있구나 생각이 들면서 이를 프로젝트에 연결시키면 어떨까 하는 재밌는 고민이 생긴거 같다 BIgQuery를 배우고 싶은데 어떤 데이터로 어떻게 다뤄야 할지 막막했던 찰라에 많은 것을 배울 수 있던 1주차 였다
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
"파티션을 나눈 테이블" 관련 질문드립니다!
안녕하세요!!원인 찾아서 해결했습니다.!
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[인프런 빅쿼리 빠짝스터디 1주차] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습문제
✅연습문제 (1) Array & Struct -- 연습문제 1) 영화 제목 별로 장르를 unnest하여 출력 -- select 절에서 새로운 이름으로 사용해야 unnest한 값이 출력됨 (기존의 array칼럼은 사용하지 않기) select title, genre from`avdanced.array_exercises` as ori ,unnest(genres) as genre --연습문제 2) 영화별로 배우와 배역을 출력. -- safe_offset 사용시, 모든 칼럼에 대하여 일일히 [0], [1].. 해줘야 하는 문제 -> UNNEST 사용. select title, ac.actor, ac.character from`avdanced.array_exercises` as ori ,unnest(actors) as ac -- 연습문제 3) title, actor, character, genre 출력 select title, ac.actor, ac.character, genre from`avdanced.array_exercises` as ori ,unnest(actors) as ac ,unnest (genres) as genre --연습문제 4) 배열을 풀기 select user_id, event_date, event_name, user_pseudo_id, eve.key, eve.value.string_value, eve.value.int_value from`avdanced.app_logs_temp` as ori , unnest (event_params) as eve where event_date = '2022-08-01' (2) Pivot 연습문제--Pivot : 집계함수(if (조건문, true일 때 값, False일때 값)) as new_column + GROUP BY (False일때의 값은 NULL또는 0으로 해주기) --1) id를 기준으로 amount sum을 pivot, order_date를 행, user_id를 열 -- 연습문제 1-1) 서브쿼리 사용하기 select order_date, sum(if(user_id=1, sum_of_amount, 0)) as user_1, sum(if(user_id=2, sum_of_amount, 0)) as user_2, sum(if(user_id=3, sum_of_amount, 0)) as user_3 from ( select order_date, user_id, sum(amount) as sum_of_amount from `avdanced.orders` group by order_date, user_id ) group by order_date order by order_date -- 연습문제 1-2) 간략하게 작성하기 select order_date, sum(if(user_id=1, amount, 0)) as user_1, sum(if(user_id=2, amount, 0)) as user_2, sum(if(user_id=3, amount, 0)) as user_3 from `.avdanced.orders` group by order_date order by order_date --연습문제 2) orde_date별로 amount의 합을 pivot (user_id row, drder_date column) -- (`)backstick을 사용하여 별칭지정 -- any_value: 그룹화할 대상 중 임의의 값을 선택(NULL 제외). any_value에서는 나머지 값이 NULL이거나 확정적으로 이값이 나올 것이다 기대할 때 사용! -- ANY_VALUE: 임의의 값을 반환하며, 특정한 규칙이나 일관성을 요구하지 않을 때 사용. (대표값, 랜덤 샘플링) -- MAX: 그룹 내에서 가장 큰 값을 반환하며, 항상 일관된 결과를 제공합니다. select user_id, sum(if(order_date='2023-05-01', amount, 0)) as `2023-05-01`, sum(if(order_date='2023-05-02', amount, 0)) as `2023-05-02`, sum(if(order_date='2023-05-03', amount, 0)) as `2023-05-03`, sum(if(order_date='2023-05-04', amount, 0)) as `2023-05-04`, sum(if(order_date='2023-05-05', amount, 0)) as `2023-05-05` from `avdanced.orders` group by user_id order by user_id -- +) 강의 내용 (any_value) -- select -- user_id, -- any_value(if(order_date='2023-05-01', amount, 0)) as `2023-05-01`, -- any_value(if(order_date='2023-05-02', amount, 0)) as `2023-05-02`, -- any_value(if(order_date='2023-05-03', amount, 0)) as `2023-05-03`, -- any_value(if(order_date='2023-05-04', amount, 0)) as `2023-05-04`, -- any_value(if(order_date='2023-05-05', amount, 0)) as `2023-05-05` -- from `avdanced.orders` -- group by user_id -- order by user_id --연습문제 3) user_id, order_date별로 주문이 있으면 1, 없으면 0으로 pivot, user_id row, order_date column. select user_id, max(if(order_date='2023-05-01', 1, 0)) as `2023-05-01`, max(if(order_date='2023-05-02', 1, 0)) as `2023-05-02`, max(if(order_date='2023-05-03', 1, 0)) as `2023-05-03`, max(if(order_date='2023-05-04', 1, 0)) as `2023-05-04`, max(if(order_date='2023-05-05', 1, 0)) as `2023-05-05` from `avdanced.orders` group by user_id order by user_id -- 연습문제 4) app_log를 pivot하기 with date_user_cnt as( select ori.user_id, ori.event_date, ori.event_name, ori.event_timestamp, ori.user_pseudo_id, max(if(eve.key = "firebase_screen", eve.value.string_value, null)) as firebase_screen, max(if(eve.key ="food_id", eve.value.int_value, null)) as food_id, max(if(eve.key ="session_id", eve.value.string_value, null)) as session_id from`avdanced.app_logs_temp` as ori , unnest (event_params) as eve where event_date ='2022-08-01' group by all ) select event_date, count(user_id) as user_cnt from date_user_cnt where event_name ="click_cart" group by event_date (3) 퍼널 연습문제-- 퍼널 별 유저수 집계 -- 1-1) UNNEST하기 & PIVOT하기 WITH base AS( SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, MAX(IF(param.key = 'food_id', param.value.int_value,NULL)) AS food_id, MAX(IF(param.key = 'session_id', param.value.string_value,NULL)) AS session_id, MAX(IF(param.key = 'firebase_screen', param.value.string_value,NULL)) AS firebase_screen, from `bigquery-432401.avdanced.app_logs_temp` , unnest (event_params) as param where event_date between '2022-08-01' and '2022-08-18' GROUP BY ALL ), base2 AS( -- 1-2) CONCAT하기 SELECT * EXCEPT (event_name, firebase_screen, event_timestamp), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM base WHERE event_name IN ("screen_view", "click_payment") ), base3 AS ( --1-3) 일자별 이벤트 별 집계 SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM base2 GROUP BY ALL HAVING step_number IS NOT NULL ) --1-4) 집계한 데이터를 PIVOT SELECT event_date, MAX(IF(base3.event_name_with_screen ="screen_view-welcome", cnt, NULL)) AS screen_view_welcome, MAX(IF(base3.event_name_with_screen ="screen_view-home", cnt, NULL)) AS screen_vie_home, MAX(IF(base3.event_name_with_screen ="screen_view-food_category", cnt, NULL)) AS screen_view_food_category, MAX(IF(base3.event_name_with_screen ="screen_view-restaurant", cnt, NULL)) AS screen_view_restaurant, MAX(IF(base3.event_name_with_screen ="screen_view-cart", cnt, NULL)) AS screen_view_cart FROM base3 GROUP BY ALL ✅배운점‘cross join unnest 칼럼 as 별칭’에서 반드시 ‘AS 별칭’ 을 이용해야 ‘Cannot access field on a value with type ARRAY’ 에러가 안 뜬다.빅쿼리에서는 ‘’이 아닌, ``을 사용하여야 한다. pivot이라고 하면 pivot()함수를 반드시 사용해야 편할 것이라고 생각했었는데, max와 if로 pivot을 구현하는 것이 인상 깊었다.SQL 기반이라고 하면 모든 DB가 비슷한 기능을 가지고 있다고 생각했는데, DB마다 생성된 함수 및 기능이 미묘하게 다르다는 것을 느꼈다. 예를 들어 빅쿼리에서 배운 countif()을 MySQL에서 사용했는데 안되는 것도 그 예가 아닐까.생각보다 빅쿼리와 PostgreSQL에서 사용하는 함수가 동일한 게 많아 인상적이었다.✅익숙해져야 할 부분퍼널 분석을 배우면서, 이론적으로 이해하는 것은 쉽지만 내가 아는 쿼리적인 지식을 실제 데이터에 적용하는 것은 생각보다 손이 많이 가고 쉽지 않은 작업이라는 것을 느꼈다. 많이 해봐야 노하우가 생길 것 같다. 어떤 데이터를 어떻게 해야 어떤 결과가 나오고, 이를 어떻게 이용하고 해석할 수 있는지에 대한 일련의 과정에 익숙해져야 할 것 같다. TIMESTAMP를 DATE로 바꾸고 확인하는 부분에 대한 연습이 필요 쿼리 작성 시, 예약어를 대문자로 사용하는 것이 좋다고 알고 있는데, 아직 이 부분이 익숙하지 않아 연습이 필요하다.코드를 작성하면서 문장을 그대로 쿼리로 옮기는 편이라서 그런지 서브 쿼리를 사용하는 경우가 많다. 단순히 문장을 쿼리로 옮기기 보다 어떻게 하면 더 간결하고 가독성 높은 쿼리를 작성할 수 있을 지 고민하는 습관을 들여야 겠다.함수 이름 정하는 거 중요한 건 아는데, 잘 안되는 것 같다. 사용 기능을 이용하여 함수 이름 짓는 습관을 지어야겠다.
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
1-4. ARRAY, STRUCT 연습문제 중 4번째 문제를 풀다 질문드립니다
강의를 들으면서 문제에 대한 답은 이해했습니다! 그런데 4번 문제 푸는 과정에서 위의 그림처럼 UNNEST안에 event_params.key를 넣어봤는데 아래의 에러가 떴습니다. 그럼 event_params는 STRUCT 구조체를 포함하는 ARRAY배열이라는 말일까요? 강의에서 array_excercised 스키마를 확인하며 event_params의 유형이 RECORD이면 보통 STRUCT 구조체를 의미한다고 말씀해주셨는데 event_params 자체는 ARRAY일까요 STRUCT일까요...?
-
미해결Flutter로 SNS 앱 만들기
섹션8 게시글 정보가져오기
app/build.gradle처음 run 하면 콘솔에 나오는 사진입나다.다시 run 하면 다음과 같이 나옵니다. 그런데 여기에서 app/build.gradle 에 이부분을 추가해서 다리 run을 하면 데이터를 받아오는 모양입니다. 다시 run을 하면 데이터를 받아오지 않고,다시 run을 하면 데이터를 받아옵니다그런데 여기서 중단하고 다시 run를 하면 에러가 발생됩니다 여기에서 아래 이부분을 삭제하면 처믐과 같은 현상입니다뭘 어떻게 해야 할지 모르겠습니다.
-
미해결BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
[빠짝스터디 1주차 과제] ARRAY, STRUCT, PIVOT, 퍼널 쿼리 연습 문제 (재미난 흐름)
이은경 - 빠짝스터디 1주차 과제 제출합니다.-- ARRAY_STRUCT 연습 문제 -- 연습문제 데이터 생성 CREATE OR REPLACE TABLE advanced.array_exercises as SELECT movie_id, title, actors, genres FROM( SELECT 1 as movie_id, 'Avengers:Endgame' as title, ARRAY<STRUCT<actor STRING, character STRING>>[ STRUCT('Robert Downey Jr.','Tony Stark'), STRUCT('Chris Evans','Steve Rogers') ] as actors, ARRAY<STRING>['Action','Adventure','Drama'] as genres UNION ALL SELECT 2, 'Inception', ARRAY<STRUCT<actor STRING, character STRING>>[ STRUCT('Leonardo Dicaprio','Cobb'), STRUCT('Joseph Gordon-Levitt','Arthur') ], ARRAY<STRING>['Action','Adventure','Sci-Fi'] UNION ALL SELECT 3, 'The Dark Knight', ARRAY<STRUCT<actor STRING, character STRING>>[ STRUCT('Christian Bale','Bruce Wayne'), STRUCT('Heath Ledger','Joker') ], ARRAY<STRING>['Action','Crime','Drama'] ); -- 연습문제 1) array_exercises table에서 title 별로 영화 genres를 UNNEST해서 보여주세요. # UNNEST(ARRAY_COLUMN) AS 새로운 이름 # SELECT 절에서 새로운 이름으로 사용한다. 기존의 ARRAY_COLUMN은 사용하지 않는다. SELECT a.title, genre FROM advanced.array_exercises as a CROSS JOIN UNNEST(genres) as genre; -- 연습문제 2) array_exercises table에서 title 별로 배우(actor)와 배역(character)을 UNNEST해서 보여주세요. 배우와 배역은 별도의 column으로 나와야 합니다. SELECT a.title, person.actor as actor, person.character as character FROM advanced.array_exercises as a CROSS JOIN UNNEST(actors) as person; -- 연습문제 3) array_exercises table에서 title 별로 배우(actor), 배역(character), 장르를 한 row에 표시되도록 출력하세요. # CROSS JOIN 하면 데이터의 중복이 어느 정도 발생, 어쩔 수 없는 이슈이다. SELECT a.title, person.actor as actor, person.character as character, genre FROM advanced.array_exercises as a CROSS JOIN UNNEST(actors) as person CROSS JOIN UNNEST(genres) as genre; -- 3)번 문제 관련 추가 # 3) 결과를 기준으로, 조건문을 사용하고 싶다. # "WHERE"를 바로 사용하면 error 발생 : 실행 순서가 FROM -> JOIN -> SELECT # actors -> UNNEST(actors) : STRUCT<actor, character> # genres -> UNNEST(genres) : STRING SELECT a.title, person.actor as actor, person.character as character, genre FROM advanced.array_exercises as a CROSS JOIN UNNEST(actors) as person CROSS JOIN UNNEST(genres) as genre WHERE person.actor='Chris Evans' -- 그냥 actor 사용하면 error 발생함 and genre='Action'; -- 연습문제 4) 앱 로그 데이터(app_logs)의 배열을 풀어주세요 SELECT a.user_id, a.event_date, a.event_name, a.user_pseudo_id, b.key as key, b.value.string_value as string_value, b.value.int_value as int_value FROM advanced.app_log as a CROSS JOIN UNNEST(event_params) as b; -- 4)번 문제 관련, 추가 사항(일 별, 사용자 수 집계) WITH base as( SELECT a.user_id, a.event_date, a.event_name, a.user_pseudo_id, b.key as key, b.value.string_value as string_value, b.value.int_value as int_value FROM advanced.app_log as a CROSS JOIN UNNEST(event_params) as b ) SELECT event_date,count(user_id) as cnt FROM base GROUP BY event_date ORDER BY event_date; ############################# -- PIVOT 연습문제 -- 연습문제 1) orders 테이블에서 유저(user_id) 별로 주문 금액(amount)의 합게를 PIVOT 해주세요. -- 날짜(order_date)를 행(Row)으로, user_id를 열로 만들어야 합니다. SELECT order_date, MAX(IF(user_id=1,amount,0)) as user_1, MAX(IF(user_id=2,amount,0)) as user_2, MAX(IF(user_id=3,amount,0)) as user_3 FROM advanced.orders GROUP BY order_date ORDER BY order_date; -- 연습문제 2) orders 테이블에서 날짜(order_date) 별로 유저들의 주문 금액(amount)의 합계를 PIVOT 해주세요. -- user_id를 행으로, order_date를 열으로 만들어야 합니다. # column name을 어떻게 지정? -- backtick(`) 사용 SELECT user_id, SUM(IF(order_date='2023-05-01',amount,0)) as `2023-05-01`, SUM(IF(order_date='2023-05-02',amount,0)) as `2023-05-02`, SUM(IF(order_date='2023-05-03',amount,0)) as `2023-05-03`, SUM(IF(order_date='2023-05-04',amount,0)) as `2023-05-04`, SUM(IF(order_date='2023-05-05',amount,0)) as `2023-05-05` FROM advanced.orders GROUP BY user_id ORDER BY user_id; -- 연습문제 3) orders 테이블에서 사용자(user_id) 별, 날짜(order_date) 별로 주문이 있다면 1, 없다면 0으로 PIVOT 해주세요. user_id를 행으로, order_date를 열로 만들고 주문을 많이 해도 1로 처리합니다. # column name을 어떻게 지정? (2번 문제와 연관) -- backtick(`) 사용 SELECT user_id, IF(SUM(IF(order_date='2023-05-01',amount,0))>0,1,0) as `2023-05-01`, IF(SUM(IF(order_date='2023-05-02',amount,0))>0,1,0) as `2023-05-02`, IF(SUM(IF(order_date='2023-05-03',amount,0))>0,1,0) as `2023-05-03`, IF(SUM(IF(order_date='2023-05-04',amount,0))>0,1,0) as `2023-05-04`, IF(SUM(IF(order_date='2023-05-05',amount,0))>0,1,0) as `2023-05-05` FROM advanced.orders GROUP BY user_id ORDER BY user_id; -- 연습문제 3번 다른 풀이 -- 특정 column 대신 "1"을 사용할 수 있다.(유무에 따라서) -- 만약, 횟수를 구해야 할 경우에는 MAX대신 SUM을 사용하면 된다. SELECT user_id, MAX(IF(order_date='2023-05-01',1,0)) as `2023-05-01`, MAX(IF(order_date='2023-05-02',1,0)) as `2023-05-02`, MAX(IF(order_date='2023-05-03',1,0)) as `2023-05-03`, MAX(IF(order_date='2023-05-04',1,0)) as `2023-05-04`, MAX(IF(order_date='2023-05-05',1,0)) as `2023-05-05` FROM advanced.orders GROUP BY user_id ORDER BY user_id; -- 연습문제 4) 앱 로그 데이터 배열 PIVOT 하기 WITH example as ( SELECT a.user_id, a.event_date, a.event_timestamp, a.event_name, a.user_pseudo_id, b.key as key, b.value.string_value as string_value, b.value.int_value as int_value FROM advanced.app_log as a CROSS JOIN UNNEST(event_params) as b WHERE event_date='2022-08-01' ) SELECT user_id, event_date, event_timestamp, event_name, user_pseudo_id, ANY_VALUE(IF(key='firebase_screen',string_value,NULL)) as firebase_screen, ANY_VALUE(IF(key='food_id',int_value,NULL)) as food_id, ANY_VALUE(IF(key='session_id',string_value,NULL)) as session_id FROM example GROUP BY ALL ORDER BY event_date, event_name; -- 퍼널 SQL 연습문제 -- 데이터 PIVOT 한 형태로 변환(시각화 용이) # with 구문으로 만든 데이터들을 저장하는 방법은...? with base_data as( SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id,platform, MAX(IF(event_params.key="firebase_screen",event_params.value. string_value,NULL)) as firebase_screen, MAX(IF(event_params.key="food_id",event_params.value.int_value,NULL)) as food_id, MAX(IF(event_params.key="session_id",event_params.value.string_value,NULL)) as session_id FROM `advanced.app_log` CROSS JOIN UNNEST(event_params) as event_params WHERE event_date between '2022-08-01' and '2022-08-18' GROUP BY ALL ), filter_event_and_concat_event_and_screen as( -- event_name + screen (필요한 이벤트만 가져올 필요가 있음) SELECT * EXCEPT(event_name, firebase_screen, food_id, event_timestamp), CONCAT(event_name,"-", firebase_screen) as event_name_with_screen, datetime(timestamp_micros(event_timestamp),"Asia/Seoul") as event_datetime FROM base_data WHERE event_name in ("screen_view","click_payment") ), funnel_data as( SELECT event_date, event_name_with_screen, case when event_name_with_screen="screen_view-welcome" then 1 when event_name_with_screen="screen_view-home" then 2 when event_name_with_screen="screen_view-food_category" then 3 when event_name_with_screen="screen_view-restaurant" then 4 when event_name_with_screen="screen_view-cart" then 5 when event_name_with_screen="click_payment-cart" then 6 else NULL end as step_number , count(distinct user_pseudo_id) as cnt FROM filter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number is not null ORDER BY event_date, step_number ) SELECT event_date, MAX(IF(step_number=1,cnt,NULL)) as `screen_view-welcome`, MAX(IF(step_number=2,cnt,NULL)) as `screen_view-home`, MAX(IF(step_number=3,cnt,NULL)) as `screen_view-food_category`, MAX(IF(step_number=4,cnt,NULL)) as `screen_view-restaurant`, MAX(IF(step_number=5,cnt,NULL)) as `screen_view-cart`, MAX(IF(step_number=6,cnt,NULL)) as `click_payment-cart` FROM funnel_data GROUP BY ALL ORDER BY event_date; 느낀 점새로운 자료형은 늘 어렵다...퍼널 분석의 큰 흐름을 배울 수 있어서 좋았습니다!의사 결정 관련 부분은 정말 많은 도움이 될 것 같습니다.connected sheet 기능 신기하네요..
-
미해결[Bloc 응용] 실전 앱 만들기 (책 리뷰 앱) : SNS 로그인, Firebase 적용, Bloc 상태 관리, GoRouter
goRouter
안녕하세요현재 get으로 toNamed를 사용해서화면이동을 하고있는데goRouter와 어떤 차이점이 있을까요? 공수를 들여서 변경해야 할 가치가 있는걸까요?
-
미해결Flutter로 SNS 앱 만들기
섹션8 게시글 정보 가져오기
데이터를 가져오지 못하고 있습니다.파일은 멜로 보냈어요
-
해결됨[Unity] 함께 만들어가는 방치형 게임 개발
리얼타임 데이터베이스 정렬보기 같은게 있을까요?
파이어베이스 리얼타임 데이터베이스에USER 하위 항목으로 저장된 내용들을 보니까제가 저장에 쓰이게 했던 변수들의 순서 나열과 다르게변수이름 시작부분 a~z 순으로 데이터가 저장되는것 같더라구요.....예를들어 제가 변수를public int zzz;public int ccc;public int aaa;이렇게 코드를 쳤다면........파이어베이스 데이터 쪽에는 (USER 하위에)public int aaa;public int ccc;public int zzz;로.... 제가 코드로 순서 맞춰 쓴 변수와 다르게a순부터 z 순까지 자동정렬 되더라구용;;이거 그냥 a~z순 말고 제가 쓴 변수 순서대로 정렬되서저장되게 하는법이 있을까요??
-
해결됨[Unity] 함께 만들어가는 방치형 게임 개발
파이어베이스 데이터베이스 불러오기 궁금한점이 있어요.
데이터 베이스 불러올때 public void ReadData() 함수에서만약에, 저장된 파일이 없을때 불러오려고 하면 에러날수도있을거같아서 혹시if(그 유저의 저장된파일이 있다면){ ReadData(); //데이터를 불러온다. }else{ return;} 이렇게 코드를 짜보고싶은데위에서 if 안에 들어갈만한 (그 유저의 저장된파일이 있다면) 에혹시 뭐라고 쓰는게 좋을까요? ㅠㅠ
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
4-3 EXECUTE IMMEDIATE 쿼리
변수 선언해서 사용할때와 EXECUTE IMMEDIATE 사용할 때의 차이점은 무엇인가요?DECLARE custom_event STRING DEFAULT 'screen_view'; SELECT COUNT(*) AS output FROM advanced.app_logs WHERE event_date = '2022-08-01' AND event_name = custom_event GROUP BY ALL
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
4-3. while 문 쿼리
예제 쿼리 결과에 대해 궁금한 점이 있어 질문 드립니다쿼리 결과 i는 11이 왜 나왔는지 궁금합니다. i 변수는 1,2,3,4,5,6,7,8,9,10,11 있는데, 쿼리 결과에서 MAX함수를 사용하지 않았는데도 11이 나온 이유는 뭔가요?쿼리 결과 sum_value는 25가 왜 나왔는지 궁금합니다.sum_value 변수는 1,3,5,7,9 (홀수) 있는데, 쿼리 결과에서 sum함수를 사용하지 않았는데도 25가 나온 이유는 뭔가요?
-
해결됨BigQuery(SQL) 활용편(퍼널 분석, 리텐션 분석)
4-2 스케줄 쿼리
스케줄 쿼리 강의를 듣다가 이해가 어려운 부분이 있어서 질문 드립니다스케줄 쿼리 작성하고 나서 특정 필터링할 때 백필 예약 하지 않고 where절에 직접 날짜 필터링해서 수정해도 될까요? 백필 예약을 하는 게 쿼리를 바꾸지 않고 날짜 필터링하는 걸로 이해했습니다!백필 예약을 할 때 쿼리에 @run_date/@run_time을 필수로 잘성해야하는 거 맞을까요?@run_date/@run_time 을 넣지 않으면 백필 예약을 해도 쿼리가 실행되지 않는 걸로 이해했습니다!