inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

[빠짝스터디 1주차 과제] ARRAY, STRUCT 연습 문제/ PIVOT 연습문제/ 퍼널 쿼리 연습 문제

138

디디

작성한 질문수 4

0

1. ARRAY, STRUCT 연습 문제

1-1)

ARRAY로 된 genres 컬럼을 평면화해 genre로 alias를 붙이고, title과 CROSS JOIN하였습니다.

SELECT
  title
  , genre
FROM advanced.array_exercises
CROSS JOIN UNNEST(genres) AS genre

 

1-2)

배우와 배역은 actor컬럼에 ARRAY<STRUCT<actor STRING, character STRING>> 타입으로 저장되어 있습니다. 우선 ARRAY를 평면화하고 .(dot)을 사용해 컬럼을 구분하였습니다.

SELECT 
  title
  , actor.actor
  , actor.character 
FROM advanced.array_exercises
CROSS JOIN UNNEST(actors) AS actor

 

1-3)

처음에는 UNNEST가 익숙하지 않아 단순히 두 데이터의 title을 키 값으로 CTE_ACTOR 테이블에 CTE_GENRE 테이블을 LEFT JOIN하자는 생각이 들었습니다.

WITH CTE_ACTOR AS (
  SELECT 
    title
    , actor.actor AS actor
    , actor.character AS character
  FROM advanced.array_exercises
  CROSS JOIN UNNEST(actors) AS actor
),
CTE_GENRE AS (
  SELECT
    title
    , genre
  FROM advanced.array_exercises
  CROSS JOIN UNNEST(genres) AS genre
)
SELECT
  A.title
  , A.actor
  , A.character
  , B.genre
FROM CTE_ACTOR A
JOIN CTE_GENRE B
  ON A.title = B.title

 

강의를 듣고는 CROSS JOIN을 두 번 해보았습니다. 배열이 각각의 행으로 풀리니 이를 두 번 실행해 결과를 얻을 수 있었고 쿼리도 훨씬 간단해졌습니다 😀

WITH CTE_ACTOR AS (
  SELECT 
    title
    , actor.actor AS actor
    , actor.character AS character
  FROM advanced.array_exercises
  CROSS JOIN UNNEST(actors) AS actor
),
CTE_GENRE AS (
  SELECT
    title
    , genre
  FROM advanced.array_exercises
  CROSS JOIN UNNEST(genres) AS genre
)
SELECT
  A.title
  , A.actor
  , A.character
  , B.genre
FROM CTE_ACTOR A
JOIN CTE_GENRE B
  ON A.title = B.title

 

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
, UNNEST(event_params) event_param
-- WHERE event_date='2022-08-02'

 

2. PIVOT 연습문제

2-1)

order_date를 기준으로 SUM을 사용해 유저 별 주문금액 합계를 구하고, 요구사항에 따라 빈 값은 0으로 채웠습니다.

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

 

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 user_id

 

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 user_id

 

2-4)

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 `string_value`
  , MAX(IF(event_param.key='session_id', event_param.value.string_value, null)) `int_value`
FROM advanced.app_logs
, UNNEST(event_params) event_param
WHERE event_date='2022-08-25'
  AND event_name='click_cart'
GROUP BY ALL

 

3. 퍼널 쿼리 연습 문제

처음엔 CASE 함수를 바로 떠올리지 못해 순서를 저장한 테이블을 만들고 JOIN해 결과를 구했습니다.

WITH CTE_STEP AS (
  SELECT 'screen_view-welcome' `event_name_with_screen`, 1 `step_number`
  UNION ALL
  SELECT 'screen_view-home', 2 
  UNION ALL  
  SELECT 'screen_view-food_category', 3 
  UNION ALL
  SELECT 'screen_view-restaurant', 4 
  UNION ALL
  SELECT 'screen_view-cart', 5
  UNION ALL
  SELECT 'click_payment-cart', 6
),
CTE_EVENT AS (
  SELECT 
    event_date
    , event_name_with_screen
    , COUNT(DISTINCT user_pseudo_id) `cnt`
  FROM (
    SELECT 
        event_date
        , user_pseudo_id
        , CONCAT(event_name, '-', event_param.value.string_value) `event_name_with_screen`
      FROM advanced.app_logs
      , UNNEST(event_params) `event_param`
      WHERE event_date BETWEEN '2022-08-01' AND '2022-08-18'
      AND event_name IN ('screen_view', 'click_payment')
      AND event_param.key = 'firebase_screen'
      AND event_param.value.string_value IN ('welcome', 'home', 'food_category', 'restaurant', 'cart')
  )
  GROUP BY event_date
    , event_name_with_screen
)
SELECT 
  A.event_date
  , A.event_name_with_screen
  , B.step_number
  , A.cnt
FROM CTE_EVENT A
JOIN CTE_STEP B 
  ON A.event_name_with_screen = B.event_name_with_screen
ORDER BY event_date, step_number

 

이후 강의를 참고해 피벗 테이블을 만들고 CASE문을 사용한 쿼리입니다.

WITH base AS (
  SELECT 
    event_date
    , event_timestamp
    , event_name
    , user_pseudo_id
    , MAX(IF(event_param.key='firebase_screen', event_param.value.string_value, null)) `firebase_screen`
    , MAX(IF(event_param.key='session_id', event_param.value.string_value, null)) `session_id`
  FROM advanced.app_logs
  , UNNEST(event_params) `event_param`
  WHERE event_date BETWEEN '2022-08-01' AND '2022-08-18'
    AND event_name IN ('screen_view', 'click_payment')
  GROUP BY ALL
), filter_event_and_concat_evnet_and_screen AS (
  SELECT 
    * EXCEPT(event_name, firebase_screen, event_timestamp)
    , CONCAT(event_name, '-', firebase_screen) `event_name_with_screen`
    , DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') `event_datetime` 
  FROM base
  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
  ELSE NULL
  END AS step_number
  , COUNT(DISTINCT user_pseudo_id)
FROM filter_event_and_concat_evnet_and_screen
GROUP BY ALL
HAVING step_number IS NOT NULL
ORDER BY event_date

 

추가로 결과 테이블을 피벗 테이블로 만들기 위한 쿼리입니다.

SELECT
  event_date
  , MAX(IF(event_name_with_screen='screen_view-welcome', cnt, 0)) `screen_view-welcome`
  , MAX(IF(event_name_with_screen='screen_view-home', cnt, 0)) `screen_view-home`
  , MAX(IF(event_name_with_screen='screen_view-food_category', cnt, 0)) `screen_view-food_category`
  , MAX(IF(event_name_with_screen='screen_view-restaurant', cnt, 0)) `screen_view-restaurant`
  , MAX(IF(event_name_with_screen='screen_view-cart', cnt, 0)) `screen_view-cart`
  , MAX(IF(event_name_with_screen='click_payment-cart', cnt, 0)) `click_payment-cart`
FROM result
GROUP BY event_date
ORDER BY event_date

 

느낀 점

 

새롭게 알게된 점

 

퍼널 분석에 대한 부분을 재밌게 수강했습니다. 퍼널 분석은 개념 정도만 알고 있었는데 퍼널을 정의하는 것에서 부터 피벗 테이블을 만들고, 시각화하기까지 실무에서의 큰 흐름을 배운 것 같아요. 팀에서 로그 설계를 진행 중인데 완료되면 간단한 퍼널 분석을 시도해보겠습니다💪🏻

 

sql Google-Analytics firebase google-sheets bigquery 인프런 빠짝스터디 빅쿼리

답변 1

0

인프런 AI 인턴

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

SQL을 사용한 데이터 평면화 및 피벗 연습 문제에 대해 질문 주셨네요. ARRAY와 STRUCT를 UNNEST해서 다양한 요소로 분리하고, 각 데이터의 구조를 명확히 하면서 PIVOT을 적용하는 연습은 데이터 분석에서 유용한 기술입니다.

  1. ARRAY, STRUCT 연습 문제 관련

    • ARRAY 타입 데이터는 UNNEST 함수를 사용하여 평면화할 수 있으며, 이를 통해 엔티티를 명확히 나누어 분석할 수 있습니다. 특히, 영화와 장르 및 배우 정보를 CROSS JOIN으로 연결하여 상세 데이터를 볼 수 있습니다.
    • STRUCT 내 필드는 .dot 연산자를 사용하여 액세스가 가능하여 복잡한 데이터 구조를 쉽게 다룰 수 있습니다.
  2. PIVOT 연습 문제 관련

    • 주문 테이블에서 SUM 함수와 조건문을 활용하여 주어진 날짜 범위나 사용자에 대해 주문 금액을 집계하여 피벗 차트를 만들 수 있습니다.

이와 관련된 유사한 문제와 해결 사례는 다음 링크에서 확인할 수 있습니다:

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

최종 과제 제출

0

87

3

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

0

87

1

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

0

85

2

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

0

80

2

biquery 테이블 생성 오류 이슈

0

59

2

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

0

76

2

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

0

69

2

array 등

0

66

2

N day 리텐션 쿼리 관련 질문

0

64

2

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

0

70

2

윈도우 연습문제 1번 질문

0

67

1

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

0

75

2

3-13 리텐션 과제 제출

0

99

2

최종 과제 제출

0

132

3

weekly retention 구하기 과제

0

90

2

1-9. 피벗 쿼리 작성

0

82

2

app_logs 테이블 생성 문제

0

73

2

Weekly Retention 구하기 완성하였습니다.

0

78

2

[과제] 퍼널 쿼리(피벗테이블 적용) 작성 완료

0

110

2

3-7 Weekly, Monthly Retention 쿼리 작성

0

93

2

정성 데이터 분석 방법 문의

0

166

1

최종 과제 제출

0

110

3

1-6 예시 문제 풀이

0

70

2

최종과제 제출

0

147

2