해결된 질문
작성
·
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
준혁님 안녕하세요! 쿼리 작성하느라 고생하셨습니다! 큰 틀은 잘 하고 계셔요. 하나씩 답변드릴게요
WITH 문 관련해서는 초보자를 위한 BigQuery(SQL) 입문 강의의 6-3 파트를 보시면 이해가 되실 것 같아요
협업하는 관점에서, 가독성이 좋지 않은 쿼리보단 가독성이 좋은 쿼리가 다른 사람들과 협업하기에 수월합니다
현업에서 일을 하다보면 중간 값을 수정해야 하는 경우가 있는데, WITH 문으로 논리적인 흐름을 나누었다면 다시 수정이 쉽습니다. 다만 모든 쿼리에 다 넣어두면 어려울 수 있죠
현업에서는 보통 100줄이 넘는 쿼리를 작성해서 특히 더 심해집니다. 과거의 내가 짠 쿼리도 미래에 까먹는 경우가 생기더라구요. 그래서 처음부터 습관을 잘 들이는 것을 추천하고 있어요
그러나 이 쿼리가 틀리냐?하면 결과가 맞다면 틀린 쿼리는 아니라 생각해요. 방식이 다른 쿼리지요. 저는 가독성도 고려하는 쿼리가 좋은 쿼리라 생각해서 WITH를 자주 활용하고 있어요
CASE WHEN에서 CASE랑 WHEN이 같은 선상에 있는데 저라면 CASE랑 WHEN을 구분할 것 같아요. 이건 초보자를 위한 BigQuery 입문 6-2에 스타일 가이드를 참고하시면 좋을 것 같아요
CASE
WHEN ~
WHEN ~
ELSE
END
일단 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 인턴입니다. 박준혁님.
작성하신 코드를 통해 PIVOT 문제를 풀어보신 것에 대해 잘 수행하셨습니다. WITH문을 사용하지 않고 한 코드에 모두 작성하는 것은 큰 문제가 되진 않지만, 쿼리의 가독성과 유지보수 측면에서 다소 불편할 수 있습니다. 각 단계별로 데이터 변환이나 집계를 명확히 구분하여 작성하면, 코드의 이해가 더 쉬워지고 버그를 찾기에도 용이해집니다.
이제 각각의 코드를 간단히 피드백 드리겠습니다.
PIVOT 전 코드
GROUP BY
문에서 특히 주의해야 할 부분은 step_number
와 같이 사용자의 단계별 처리를 포함하여 적절히 그룹화가 되었는지 확인하는 것입니다. 현재 코드는 전체적으로 큰 오류는 없습니다.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 및 퍼널 쿼리를 작성할 때 발생할 수 있는 다양한 문제 및 해결 방법을 제시하고 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
감사합니다! 카일님! 참고해서 다시 한번 리팩토링 해보겠습니다!