작성
·
16
0
CREATE OR REPLACE TABLE advanced.array_excercised AS #DDL
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']
)
→ actors라는 STRUCT 구조체를 만들고 그 안에 2개의 필드 actor와 character를 지정하고, STRUCT 구조체 2개를 list처럼 ARRAY에 넣은 것.
위의 테이블을 가지고 연습문제 1~4번 진행
array_excercises 테이블에서 각 영화(title)별로 장르(genres)를 UNNEST해서 보여주세요.
SELECT
title,
genre
FROM advanced.array_excercised
CROSS JOIN UNNEST(genres) AS genre
array_excercised 테이블에서 각 영화(title)별로 배우(actor)와 배역(character)을 보여주세요. 배우와 배역은 별도의 컬럼으로 나와야 합니다.
SELECT
title,
actor.actor,
actor.character
FROM advanced.array_excercised
CROSS JOIN UNNEST(actors) AS actor
actors ARRAY안에 2개의 STRUCT 구조체가 있는 구조이므로 ARRAY 데이터에 접근하는 방법으로 데이터에는 접근 가능
actors[SAFE_OFFSET(0)].actor AS first_actor
array_excercises 테이블에서 각 영화(title)별로 배우(actor), 배역(character), 장르(genre)를 출력하세요. 한 Row에 배우, 배역, 장르가 모두 표시되어야 합니다.
SELECT
title,
actor.actor,
actor.character,
genre
FROM advanced.array_excercised
CROSS JOIN UNNEST(actors) AS actor
CROSS JOIN UNNEST(genres) AS genre
*UNNEST를 2번 연속 사용할 수 있다.
*쿼리문의 실행순서는 FROM → JOIN → SELECT 이다. UNNEST를 통해 만들어진 actor는 현재 actor.actor가 아니라 actor라는 STRUCT 구조체이므로 구조체에 바로 접근할 수 없다는 에러가 뜰 수 있다.
앱 로그 데이터(app_logs)의 배열을 풀어주세요.
SELECT
event_date,
event_timestamp,
event_name,
event_param.key AS key,
event_param.value AS value,
user_id,
user_pseudo_id,
platform
FROM advanced.app_logs
CROSS JOIN UNNEST(event_params) AS event_param
event_params는 RECORD라고 되어있는데 STRUCT이다. 중첩된 구조라는 의미.
PIVOT 연습문제
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_date
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_id
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
4. user_id = 32888이 카트 추가하기(click_cart)를 누를 때 어떤 음식(food_id)을 담았나요?
WITH base AS(
SELECT
#* EXCEPT(event_params),
event_date,
event_timestamp,
event_name,
event_param.key AS key,
event_param.value.string_value AS string_value,
event_param.value.int_value AS int_value,
user_id,
user_pseudo_id,
platform
FROM advanced.app_logs
CROSS JOIN UNNEST(event_params) AS event_param
)
SELECT
user_id,
event_date,
event_name,
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 base
WHERE
user_id = 32888
AND event_name = 'click_cart'
GROUP BY
user_id,
event_date,
event_name
퍼널별 전환율을 쉽게 구할 수 있도록 PIVOT 해보기
WITH base AS (
SELECT
event_date,
event_timestamp,
event_name,
user_id,
user_pseudo_id,
platform,
#event_param,
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
), 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 base
WHERE
event_name IN ("screen_view", "click_payment")
), funnel_analysis 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
)
SELECT
event_date,
MAX(IF (event_name_with_screen = "screen_view-welcome", cnt, NULL)) AS `screen_view-welcome`,
MAX(IF (event_name_with_screen = "screen_view-home", cnt, NULL)) AS `screen_view-home`,
MAX(IF (event_name_with_screen = "screen_view-food_category", cnt, NULL)) AS `screen_view-food_category`,
MAX(IF (event_name_with_screen = "screen_view-restaurant", cnt, NULL)) AS `screen_view-restaurant`,
MAX(IF (event_name_with_screen = "screen_view-cart", cnt, NULL)) AS `screen_view-cart`,
MAX(IF (event_name_with_screen = "click_payment-cart", cnt, NULL)) AS `click_payment-cart`
FROM funnel_analysis
GROUP BY ALL
ORDER BY event_date
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 민영 김님.
BigQuery에서 사용하는 ARRAY, STRUCT, 그리고 PIVOT 등의 기능을 통해 데이터를 시각화하고 분석하는 과정은 매우 흥미롭습니다. 이렇게 다양한 SQL 쿼리를 작성하면서 데이터 분석의 기본기를 탄탄히 다지는 것은 큰 강점이 될 것입니다.
질문 주신 array_excercised 테이블을 통해서 연습한 문제들은 영화/배우 데이터의 구조를 활용해 BigQuery의 UNNEST 기능을 익히는 좋은 기회가 됩니다. 또한 PIVOT 문제에서는 다양한 방식으로 데이터를 집계하는 연습을 하셨고, 이는 데이터 분석에 매우 유용한 기술입니다.
다음은 관련된 기존의 질문과 답변을 찾아 소개드립니다. 퍼널 분석 및 PIVOT을 통해 데이터를 시각화하고 전환율을 구하는 데 도움이 되길 바랍니다.
구글 스프레드시트 사용 시 데이터 로그 설계에 대한 질문
여기서는 데이터의 파라미터 설계 및 이를 활용한 분석 방법에 대한 논의가 있습니다. 관련 프로젝트에 도움이 될 것입니다.
퍼널 SQL 쿼리 작성하기 - 오류 해결 사례
퍼널 쿼리 작성 중 발생할 수 있는 오류와 그 해결책들을 다루고 있어 실질적인 쿼리 작성 시 참고가 될 수 있습니다.
현재 베타 기능으로 제공되는 답변입니다만, 관련 자료가 만족스럽지 않을 경우 추가적으로 문의 주시면 지식공유자분께서 더 상세한 답변으로 도움을 주실 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.