작성
·
23
0
문제 1) User들의 다음 접속 월과 다다음 접속 월을 구하는 쿼리를 작성해주세요
select
*,
lead(visit_month) over (partition by user_id order by visit_month) as next_visit_month,
lead(visit_month, 2) over (partition by user_id order by visit_month) as next_visit_month2
from advanced.analytics_function_01
;
결과
문제 2) User들의 다음 접속 월과 다다음 접속 월, 이전 접속 월을 구하는 쿼리 작성
select
*,
lead(visit_month, 1) over (partition by user_id order by visit_month) as next_visit_month,
lead(visit_month, 2) over (partition by user_id order by visit_month) as next_visit_month2,
lag(visit_month, 1) over (partition by user_id order by visit_month) as pre_visit_month
from advanced.analytics_function_01
order by user_id, visit_month
결과
문제 3) user가 접속했을 때, 다음접속까지의 간격을 구하시오
select
*,
next_visit_month - visit_month as term
From (
select
*,
lead(visit_month, 1) over (partition by user_id order by visit_month) as next_visit_month
from advanced.analytics_function_01)
order by user_id, visit_month
;
결과
추가문제 : 이 데이터셋을 User_id의 첫번째 방문 월, 마지막 방문월을 구하는 쿼리 작성
select
*,
first_value(visit_month) over (partition by user_id order by visit_month ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as first_visit_month,
last_value(visit_month) over (partition by user_id order by visit_month ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as last_visit_month
from advanced.analytics_function_01
order by user_id, visit_month
;
결과
Frame 연습문제
select
*,
sum(amount) over() as amount_total,
sum(amount) over(order by order_id) as cumulative_sum, -- 누적
sum(amount) over(partition by user_id order by order_id) as cumulative_sum_user, -- 누적
avg(amount) over(order by order_id rows between 5 preceding and 1 preceding) as last_5_avg
from `advanced.orders`
order by order_date, user_id
;
결과
1) 사용자별 쿼리를 실행한 총 횟수를 구하는 쿼리를 작성해주세요. 단, GROUP BY를 사용해서 집계하는 것이 아닌 query_logs의 데이터의 우측에 새로운 컬럼을 만들어주세요.
select
*,
count(query_date) over() as total_cnt, # 전체
count(query_date) over(partition by user) as total_query_cnt
from advanced.query_logs
order by user, query_date
;
결과
2) 주차별로 팀 내에서 쿼리를 많이 실행한 수를 구한 후, 실행한 수를 활용해 랭킹을 구해주세요. 단, 랭킹이 1등인 사람만 결과가 보이도록 해주세요
with query_cnt_by_team as (
select
extract(WEEK from query_date) as week_number,
team,
user,
count(user) as query_cnt
from advanced.query_logs
group by all)
select
*,
rank() over(partition by week_number, team order by query_cnt desc) as team_rank
from query_cnt_by_team
qualify team_rank = 1
order by week_number, team, query_cnt desc
;
결과
3) (2번 문제에서 사용한 주차별 쿼리 사용) 쿼리를 실행한 시점 기준 1주 전에 쿼리 실행 수를 별도의 컬럼으로 확인할 수 있는 쿼리를 작성해주세요
with query_cnt_by_team as (
select
user,
team,
extract(WEEK from query_date) as week_number,
count(user) as query_cnt
from advanced.query_logs
group by all)
select
*,
LAG(query_cnt, 1) OVER (partition by user ORDER BY week_number) AS prev_week_query_count
-- user 단위, 전주차 week_number
from query_cnt_by_team
-- order by user -- team, query_cnt desc
;
결과
4) 시간의 흐름에 따라, 일자별로 유저가 실행한 누적 쿼리 수를 작성해주세요
select
*,
sum(query_cnt) over(partition by user order by query_date) as cumulative_sum,
-- 왜되는거지? : frame의 default값 : unbounded preceding ~current row
sum(query_cnt) over(partition by user order by query_date rows between unbounded preceding and current row) as cumulative_sum2
from (select
user,
team,
query_date,
count(*) as query_cnt
from advanced.query_logs
group by all)
-- 검증
-- qualify cumulative_sum != cumulative_sum2
order by user, query_date
;
결과
5) 다음 데이터는 주문 횟수를 나타낸 데이터입니다. 만약 주문 횟수가 없으면 NULL로 기록됩니다. 이런 데이터에서 NULL 값이라고 되어있는 부분을 바로 이전 날짜의 값으로 채워주는 쿼리를 작성해주세요
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
*,
LAG(number_of_orders) over(order by date) as number_of_orders2,
ifnull(number_of_orders, LAG(number_of_orders) over(order by date)) as number_of_orders3,
LAST_VALUE(number_of_orders) over(order by date) as last_value_orders,
LAST_VALUE(number_of_orders ignore nulls) over(order by date) as last_value_orders2
FROM raw_data
;
결과
6) 5번 문제에서 NULL을 채운 후, 2일 전 ~ 현재 데이터의 평균을 구하는 쿼리를 작성해주세요(이동 평균)
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 * from raw_data;
select
* ,
avg(number_of_orders) over(order by date rows between 2 preceding and current row) as moving_avg
from (SELECT
* except(number_of_orders),
LAST_VALUE(number_of_orders ignore nulls) over(order by date) as number_of_orders
FROM raw_data)
;
결과
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_data as(
select
*,
datetime_diff(event_datetime, prev_event_datetime, second) as second_diff -- second로 간격설정
# second_diff기반으로 새로운 세션의 시작일지 아닐지 판단할 수 있음
from(select
*,
lag(event_datetime, 1) over(partition by user_pseudo_id order by event_datetime) as prev_event_datetime
# event_datetime이랑 prev_event_datetime을 빼서 20초가 넘으면 새로운 세션으로 정의,
# 20초가 넘지 않으면 기존 세션
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
# session이 시작됨을 알리는 session_start
from diff_data)
order by event_datetime
limit 20;
결과
마지막 문제같은 실무에 사용 할 법한 예제 문제들을 더 만들어서 풀어봐야 할 것 같다.
session기준에 대한 리서치를 더 해봐야 할 것 같다.
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 지용님.
질문하신 내용을 바탕으로 몇 가지 유사한 질문과 답변을 소개드리겠습니다. 윈도우 함수와 관련된 다양한 활용 예제들은 SQL의 깊이 있는 사용법을 이해하는 데 큰 도움이 될 것입니다. 아래의 링크들이 지용님의 학습에 도움이 되길 바랍니다.
Bigquery 활용편(PDF)파일 P.229 페이지 코드 오류
퍼널별 유저들의 새로운 세션 시작 횟수의 총합 _ 윈도우 함수 마지막 문제 응용
3-7 리텐션 SQL 쿼리 작성하기 연습 (Weekly, Monthly)
이 자료들은 윈도우 함수를 사용한 다양한 분석 사례를 제시하며, 실무적인 문제 해결 능력을 키우는데 큰 도움이 될 것입니다. 계속해서 학습하시면서 궁금한 점이 생기면 언제든지 질문해 주세요.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.