채널톡 아이콘

인프런 커뮤니티 질문&답변

박준혁님의 프로필 이미지

작성한 질문수 1

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

1-9. 퍼널 SQL 쿼리 작성하기

1-9 PIVOT문제 풀기

해결된 질문

작성

·

61

0

안녕하세요 카일스쿨님!

1-9 PIVOT문제를 풀어봤습니다.

먼저 PIVOT전에 제방식대로 푼코드를 드리겠습니다. 제가 WITH문을 자주 쓰지않고 그냥 한코드에 다쓰는 습관이 있어서 이런식으로 코드를 짜면 안좋은점이 있는지 피드백받고싶습니다. 또한 PIVOT문제를 풀긴 했는데 맞는 답인지 피드백받고싶습니다.

-- PIVOT하기전에 제가 푼 것

-- 내가 쓴 답
-- SELECT
--   event_date,
--   concat(event_name,'-',  param.value.string_value) AS event_name_with_screen,
--   CASE 
--   WHEN (event_name='screen_view' AND param.value.string_value='welcome') THEN 1
--   WHEN (event_name='screen_view' AND param.value.string_value='home') THEN 2
--   WHEN (event_name='screen_view' AND param.value.string_value='food_category') THEN 3
--   WHEN (event_name='screen_view' AND param.value.string_value='restaurant') THEN 4
--   WHEN (event_name='screen_view' AND param.value.string_value='cart') THEN 5
--   WHEN (event_name = 'click_payment' AND param.value.string_value='home') THEN 6
--   ELSE 0
--   END AS step_number,
--   COUNT(DISTINCT user_id) AS cnt
-- FROM `expanded-idiom-446706-d4.advanced.app_logs`
-- CROSS JOIN UNNEST(event_params) AS param
-- WHERE 
-- (event_date BETWEEN "2022-08-01"AND '2022-08-18') AND key='firebase_screen'  
-- GROUP BY event_date,event_name,param.value.string_value,step_number
-- HAVING step_number !=0
-- ORDER BY step_number ,event_date

-- PIVOT문제 푼것

 

 

 


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.string_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'
GROUP BY ALL
) , fliter_event_and_concat_evnet_and_screen AS(
-- screen과 event_name을 합치자(필요한 이벤트만 where 조건에걸어서 사용)
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')
)



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

답변 2

1

카일스쿨님의 프로필 이미지
카일스쿨
지식공유자

준혁님 안녕하세요! 쿼리 작성하느라 고생하셨습니다! 큰 틀은 잘 하고 계셔요. 하나씩 답변드릴게요

 

1. WITH 문 질문.

  • WITH 문 관련해서는 초보자를 위한 BigQuery(SQL) 입문 강의의 6-3 파트를 보시면 이해가 되실 것 같아요

  • 협업하는 관점에서, 가독성이 좋지 않은 쿼리보단 가독성이 좋은 쿼리가 다른 사람들과 협업하기에 수월합니다

  • 현업에서 일을 하다보면 중간 값을 수정해야 하는 경우가 있는데, WITH 문으로 논리적인 흐름을 나누었다면 다시 수정이 쉽습니다. 다만 모든 쿼리에 다 넣어두면 어려울 수 있죠

  • 현업에서는 보통 100줄이 넘는 쿼리를 작성해서 특히 더 심해집니다. 과거의 내가 짠 쿼리도 미래에 까먹는 경우가 생기더라구요. 그래서 처음부터 습관을 잘 들이는 것을 추천하고 있어요

  • 그러나 이 쿼리가 틀리냐?하면 결과가 맞다면 틀린 쿼리는 아니라 생각해요. 방식이 다른 쿼리지요. 저는 가독성도 고려하는 쿼리가 좋은 쿼리라 생각해서 WITH를 자주 활용하고 있어요

  • CASE WHEN에서 CASE랑 WHEN이 같은 선상에 있는데 저라면 CASE랑 WHEN을 구분할 것 같아요. 이건 초보자를 위한 BigQuery 입문 6-2에 스타일 가이드를 참고하시면 좋을 것 같아요

CASE
  WHEN ~
  WHEN ~
  ELSE
END

 

2. PIVOT 문제

  • 일단 WITH에서 아래에 SELECT가 바로 붙어서 나오는데 저는 탭 한번 칠 것 같아요

WITH base AS (
  SELECT 
    ..
  FROM ..
)
  • 아래 쿼리도 탭을 적절히 사용해서 가독성을 높일 것 같아요

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')
  • 쿼리를 보니까 IF문에 괄호 위치가 잘못되어 있어요

    • IF(event_name_with_screen='screen_view-welcome', cnt) 이런 형태로 되어야 합니다. 지금은 cnt 전에 괄호가 닫혀있어요

  • 그리고 fliter_event_and_concat_evnet_and_screen 에 cnt가 없는데 cnt를 SUM하고 계시네요. 중간 집계를 하시려는 의도일까요?

  • 일단 피벗 쿼리는 쿼리 실행이 안되어서 실행되는 형태로 만들어 보는 것이 먼저일 것 같네요

박준혁님의 프로필 이미지
박준혁
질문자

감사합니다! 카일님! 참고해서 다시 한번 리팩토링 해보겠습니다!

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다. 박준혁님.

작성하신 코드를 통해 PIVOT 문제를 풀어보신 것에 대해 잘 수행하셨습니다. WITH문을 사용하지 않고 한 코드에 모두 작성하는 것은 큰 문제가 되진 않지만, 쿼리의 가독성과 유지보수 측면에서 다소 불편할 수 있습니다. 각 단계별로 데이터 변환이나 집계를 명확히 구분하여 작성하면, 코드의 이해가 더 쉬워지고 버그를 찾기에도 용이해집니다.

이제 각각의 코드를 간단히 피드백 드리겠습니다.

  1. PIVOT 전 코드

    • 코드는 잘 작성되었습니다. 다만, 데이터의 그룹화를 위해 GROUP BY 문에서 특히 주의해야 할 부분은 step_number와 같이 사용자의 단계별 처리를 포함하여 적절히 그룹화가 되었는지 확인하는 것입니다. 현재 코드는 전체적으로 큰 오류는 없습니다.
  2. PIVOT 문제 풀기

    • 기존 코드를 PIVOT 형태로 변형하려는 시도는 좋습니다. WITH 절을 사용하여 코드를 더 구조적으로 작성한 점, 그리고 중요한 필드를 명확히 추출한 점이 돋보입니다.

    • 하지만 다음과 같은 부분에서 수정이 필요할 수 있습니다:

      • SUM(IF(event_name_with_screen='screen_view-welcome'),cnt,0) 부분에서, 각 조건문이 잘못되어 있습니다. IF 문 안에서 조건과 수행문 사이에 콤마(,)가 있어야 하는데, 오히려 괄호 안에서 콤마를 잘못 위치한 것이 보입니다. 이 점을 수정해 SUM(CASE WHEN event_name_with_screen='screen_view-welcome' THEN cnt ELSE 0 END) 형태로 바꾸실 수 있습니다.

      • 마지막에는 모든 그룹화에 GROUP BY ALL을 적용하지 말고, 실제로 필요한 열 (여기서는 event_date)에만 그룹화하는 것이 일반적입니다.

이와 관련하여 유사한 주제를 다룬 예시들을 살펴보실 수 있는 링크를 제공드립니다.

위 예시에서는 PIVOT 및 퍼널 쿼리를 작성할 때 발생할 수 있는 다양한 문제 및 해결 방법을 제시하고 있습니다.

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