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

김덕배님의 프로필 이미지
김덕배

작성한 질문수

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

빠짝스터디 2주차 윈도우 함수

작성

·

31

·

수정됨

0

  1.  

--1. 사용자별 쿼리를 실행한 총 횟수를 구하는 쿼리를 작성해주세요. 단, group by를 사용해서 집곟나ㅡㄴ 것이 아닌 query_logs의 데이터의 우측에 새로운 컬럼을 만들어주세요.


select
  *,
  count(query_date) over(partition by user) as total_query_cnt
from
  advanced.query_logs
order by 1, 3
  1.  

--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 rk
from
  query_cnt_by_team
qualify rk = 1
order by 1, 2, 4 desc

  1.  

-- 3. (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
  *,
  lag(query_cnt, 1) over(partition by user order by week_number) as prev_week_query_cnt
from
  query_cnt_by_team
  1.  

-- 4. 시간의 흐름에 따라 일자별로 유저가 실행한 누적 쿼리 수를 작성해주세요.

select
  *,
  sum(query_cnt) over (partition by user order by query_date rows between unbounded preceding and current row) as cumulative_sum
from
  (
  select
    query_date,
    user,
    count(user) as query_cnt
  from
    advanced.query_logs
  group by all
  )
order by 2, 1
  1.  

-- 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
),

raw_data2 as(
  select
    *,
    last_value(raw_data.number_of_orders ignore nulls) over(order by date) as last_value_orders
  from
    raw_data
)
select
  *
from
  raw_data2
  1.  

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
),

raw_data2 as(
  select
    *,
    last_value(raw_data.number_of_orders ignore nulls) over(order by date) as last_value_orders
  from
    raw_data
)


--6. 5번 문제에서 NULL을 채운 후, 2일 전 ~ 현재 데이터의 평균을 구하는 쿼리를 작성해주세요(이동평균)

select
  * except(number_of_orders),
  avg(last_value_orders) over (order by date rows between 2 preceding and current row) as moving_avg
from
  raw_data2
  1.  

--7. app_logs 테이블에서 Custom session을 만들어 주세요. 이전 이벤트 로그와 20초가 지나면 새로운 session을 만들어 주세요. session은 숫자로 (1, 2, 3..) 표시해도 됩니다.
-- 2022-08-18의 user_pseudo_id(1997494153.8491999091)은 session_id가 4까지 나옵니다

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
    event_date = "2022-08-18"
    and user_pseudo_id = "1997494153.8491999091"
  order by event_timestamp
),

diff_data as 
  (
  select
    *,
    datetime_diff(event_datetime, prev_event_datetime, second) as second_diff
  from
    (
    select
      *,
      lag(event_datetime, 1) over(partition by user_pseudo_id order by event_datetime) as prev_event_datetime
    from
      base
    order by 
      event_datetime
    )
  )

select
  *,
  sum(session_start) over(partition by user_pseudo_id order by event_datetime) as session_number
from
  (
  select
    *,
    case
      when prev_event_datetime is null then 1
      when second_diff >= 20 then 1
      else null
    end as session_start
  from
    diff_data
  )

 

 

 

답변 1

0

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

문의해주신 윈도우 함수 사용에 대한 다양한 SQL 연습 문제를 작성해주셨네요. 각 쿼리마다 구체적인 분석이 필요할 수 있는 중요한 부분이 많습니다. 아래는 이 문제들 중에서 관련된 내용을 설명하고, 똑같은 주제에 대한 다른 학습자가 올린 질문과 답변을 찾았습니다.

사용자별 쿼리 총 횟수

1. 사용자별 쿼리 횟수를 구하기: 이 쿼리는 사용자별로 쿼리를 실행한 총 횟수를 계산하고 있습니다. count(query_date)over(partition by user)와 함께 사용하여 각 사용자의 총 쿼리 수를 구합니다. 이는 각 row에 대하여 계산되며, 데이터를 살펴보는 데 큰 도움이 됩니다.

주차별 랭킹 구하기

2. 주차별 랭킹 구하기: 팀 내에서 특정 주차에 가장 많이 쿼리를 실행한 사용자를 찾기 위해 사용한 방법으로, rank() 윈도우 함수를 사용하여 그룹별로 가장 높은 순위를 계산하였습니다.

3-7 리텐션 SQL 쿼리 작성하기 연습 (Weekly, Monthly) 게시물에서는 비슷한 윈도우 함수 활용에 대한 연습과 피드백을 볼 수 있습니다.

일자별 누적 쿼리 수 구하기

4. 누적 쿼리 수 계산: 시간의 흐름에 따라 유저가 수행한 누적 쿼리 수를 구하는 부분입니다. 여기서는 sum() 윈도우 함수와 함께 rows between unbounded preceding and current row를 사용하였습니다.

windows function default 값에 대하여 range between과 rows between의 차이에서는 ROWSRANGE의 차이를 다룬 설명을 제공하고 있습니다. 각 함수의 기본 동작을 이해하는 데에 유용할 것입니다.

NULL 채우기

5. NULL 값을 이전 값으로 채우기: 이런 상황에서는 last_value 같은 윈도우 함수들을 활용하여 NULL 값을 확인하고 반복적으로 값을 채울 수 있습니다. 쿼리 예제에서는 last_value()를 통해 NULL 값을 이전 날짜 값으로 채우는 방법을 보여줍니다.

각 문제를 해결하기 위해 사용된 SQL 기법들을 잘 이해하고 활용하셨습니다. 유사한 질문과 답변을 참고하시어 더 깊이 있는 이해를 얻을 수 있기를 바랍니다.

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

김덕배님의 프로필 이미지
김덕배

작성한 질문수

질문하기