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

DataPirate님의 프로필 이미지
DataPirate

작성한 질문수

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

[빠짝스터디 2주차 과제] 윈도우 함수 연습 문제

작성

·

32

0

#1

SELECT
  *,
  LEAD(visit_month, 1) OVER(PARTITION BY user_id ORDER BY visit_month) AS lead_visit_month1,
  LEAD(visit_month, 2) OVER(PARTITION BY user_id ORDER BY visit_month) AS lead_visit_month2 
FROM advanced.analytics_function_01
ORDER BY user_id;

#2

SELECT
  *,
  LEAD(visit_month, 1) OVER(PARTITION BY user_id ORDER BY visit_month) AS after_visit_month1,
  LEAD(visit_month, 2) OVER(PARTITION BY user_id ORDER BY visit_month) AS after_visit_month2,
  LAG(visit_month, 1) OVER(PARTITION BY user_id ORDER BY visit_month) AS before_visit_month1
FROM advanced.analytics_function_01
ORDER BY
  user_id,
  visit_month;

#3

SELECT
  *,
  after_visit_month - visit_month AS diff
FROM (
  SELECT
    *,
    LEAD(visit_month, 1) OVER (PARTITION BY user_id ORDER BY visit_month) AS after_visit_month,
  FROM advanced.analytics_function_01
);

#4

SELECT
  *,
  FIRST_VALUE(visit_month) OVER (PARTITION BY user_id ORDER BY visit_month ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first,
  LAST_VALUE(visit_month) OVER (PARTITION BY user_id ORDER BY visit_month ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last
FROM advanced.analytics_function_01;

#5

SELECT
  *,
  COUNT(user) OVER(PARTITION BY user) AS total_query_cnt
FROM advanced.query_logs
ORDER BY
  user,
  query_date;

#6

WITH query_cnt_cnt AS (
  SELECT
    EXTRACT(WEEK FROM query_date) AS week_number,
    team,
    user,
    COUNT(*) AS query_cnt
  FROM advanced.query_logs
  GROUP BY
    week_number,team,user
)
SELECT
  *,
  RANK() OVER(PARTITION BY week_number, team ORDER BY query_cnt DESC) AS rk
FROM query_cnt_cnt
QUALIFY rk = 1
ORDER BY
  week_number,
  team,
  query_cnt DESC;

#7

WITH query_cnt_cnt AS (
  SELECT
    EXTRACT(WEEK FROM query_date) AS week_number,
    team,
    user,
    COUNT(*) AS query_cnt
  FROM advanced.query_logs
  GROUP BY
    week_number,team,user
)
SELECT
  *,
  LAG(query_cnt, 1) OVER (PARTITION BY user ORDER BY week_number) AS prev_week_query_cnt
FROM query_cnt_cnt;

#8

WITH query_cnt AS (
  SELECT
    *,
    COUNT(*) AS query_cnt_cnt
  FROM advanced.query_logs
  GROUP BY
    user, team, query_date
)
SELECT
  *,
  SUM(query_cnt_cnt) OVER (PARTITION BY user ORDER BY query_date ) AS query_cnt_cnt_cnt
FROM query_cnt;

#9

WITH raw_data AS (
  SELECT DATE '2024-05-01' AS date, 15 AS number_of_orders 
  UNION ALL 
  SELECT DATE '2024-05-02', 13 
  UNION ALL
  SELECT DATE '2024-05-03', NULL 
  UNION ALL
  SELECT DATE '2024-05-04', 16 
  UNION ALL
  SELECT DATE '2024-05-05', NULL 
  UNION ALL
  SELECT DATE '2024-05-06', 18 
  UNION ALL
  SELECT DATE '2024-05-07', 20 
  UNION ALL
  SELECT DATE '2024-05-08', NULL 
  UNION ALL
  SELECT DATE '2024-05-09', 13 
  UNION ALL
  SELECT DATE '2024-05-10', 14 
  UNION ALL
  SELECT DATE '2024-05-11', NULL
  UNION ALL
  SELECT DATE '2024-05-12', NULL
)

SELECT
  *,
  LAST_VALUE(number_of_orders IGNORE NULLS) OVER (ORDER BY date) AS last_value_orders
FROM raw_data;

#10

WITH raw_data AS (
  SELECT DATE '2024-05-01' AS date, 15 AS number_of_orders 
  UNION ALL 
  SELECT DATE '2024-05-02', 13 
  UNION ALL
  SELECT DATE '2024-05-03', NULL 
  UNION ALL
  SELECT DATE '2024-05-04', 16 
  UNION ALL
  SELECT DATE '2024-05-05', NULL 
  UNION ALL
  SELECT DATE '2024-05-06', 18 
  UNION ALL
  SELECT DATE '2024-05-07', 20 
  UNION ALL
  SELECT DATE '2024-05-08', NULL 
  UNION ALL
  SELECT DATE '2024-05-09', 13 
  UNION ALL
  SELECT DATE '2024-05-10', 14 
  UNION ALL
  SELECT DATE '2024-05-11', NULL
  UNION ALL
  SELECT DATE '2024-05-12', NULL
), filled_data AS (
  SELECT
    * EXCEPT(number_of_orders),
    LAST_VALUE(number_of_orders IGNORE NULLS) OVER (ORDER BY date) AS number_of_orders
  FROM raw_data
)
SELECT
  *,
  AVG(number_of_orders) OVER(ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM filled_data

#11

WITH base AS (
SELECT
  event_date,
  DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime,
  event_name,
  user_id,
  user_pseudo_id
FROM advanced.app_logs
WHERE
  1=1
  AND event_date = "2022-08-18"
  AND user_pseudo_id = "1997494153.8491999091"
) , diff_date AS (
  SELECT
    *,
    DATETIME_DIFF(event_datetime, prev_event_datetime, SECOND) AS second_diff
    # second_diff 기반으로 새로운 세션의 시작일지, 아닐지를 판단할 수 있음
  FROM(
    SELECT
      *,
      LAG(event_datetime, 1) OVER(PARTITION BY user_pseudo_id ORDER BY event_datetime) AS prev_event_datetime
      -- DATETIME_DIFF() => 차이를 구할 수 있음
    FROM base
  )
)
SELECT
  *,
  SUM(session_start) OVER(PARTITION BY user_pseudo_id ORDER BY event_datetime) AS session_num
FROM (
  SELECT
    *,
    CASE
      WHEN prev_event_datetime IS NULL THEN 1
      WHEN second_diff >= 20 THEN 1 
      ELSE 0
      END AS session_start
  FROM diff_data
  ORDER BY
    event_datetime
)

 

 

답변 1

0

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

윈도우 함수를 활용한 SQL 쿼리 작성 연습 문제에 대한 질문을 올려주셨군요! 윈도우 함수는 데이터를 분석하고 비교 결과를 손쉽게 얻을 수 있도록 도와주는 강력한 도구입니다. 이번 과제를 통해 다양한 윈도우 함수의 사용법을 실습해보신 것 같습니다.

각 쿼리의 주요 부분을 간단히 설명드리겠습니다:

  1. LEAD 함수를 사용하여 현재 행 기준으로 이후의 데이터를 가져오는 방법을 연습합니다. 이는 사용자 ID별로 방문 데이터를 비교할 때 유용합니다.

  2. LAG 함수는 이전 행의 데이터를 가져오는 데 사용됩니다. 사용자 행동의 변화를 추적할 수 있습니다.

  3. LEAD 함수와 함께 수학 연산을 사용하여 데이터를 분석하고 변화를 측정합니다.

  4. FIRST_VALUE 및 LAST_VALUE 함수를 사용하여 각 파티션 내 첫 번째 및 마지막 값을 가져옵니다. 이 구문을 사용할 때 프레임 (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)을 지정해야 올바른 결과를 얻을 수 있다는 점에 주의해야 합니다.

  5. 윈도우 함수에서 COUNT 사용은 그룹 내 요소 수를 계산할 때 사용합니다.

6-8. RANK 및 SUM과 같은 집계 함수를 통해 데이터를 그룹화하고 정렬하며 누적 합계를 계산하는 방법을 이해할 수 있습니다.

9-10. NULL 처리와 이동 평균을 계산하는 방식을 활용하여 데이터 간의 공백을 처리하고 시간 간격에 따른 값을 추정합니다.

  1. 이벤트 로그 데이터에서 세션 시작 판단: LAG 및 조건문을 사용하여 각 이벤트 간 시간을 비교하여 새로운 세션의 시작을 식별합니다.

이 연습을 통해 다양한 시나리오에서 윈도우 함수를 적용하고 분석 하도록 고안된 쿼리로 보입니다.

유사한 질문이나 관련된 이전 답변 예시는 아래 링크에서 찾아보실 수 있습니다:

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

DataPirate님의 프로필 이미지
DataPirate

작성한 질문수

질문하기