문제
SQLite
내가 작성한 정답
- a 테이블에서 row_number으로 시간의 흐름에 따라 번호를 매겼다.
- b 테이블에서 a 테이블끼리 join하여 시간차이가 1시간이상 난 레코드들을 걸러내고
- row_number으로 번호를 매겼다. → 다음에 self join하기 위함
- 최종쿼리에서 b테이블을 셀프조인해서 시작과 끝을 맞췄다.
with a as (select row_number() over (order by event_timestamp_kst) t,
event_timestamp_kst,
user_pseudo_id
from ga
where user_pseudo_id = 'S3WDQCqLpK'),
b as (select row_number() over(order by a.event_timestamp_kst) tt,
b.event_timestamp_kst ss,
a.event_timestamp_kst ee,
b.user_pseudo_id
from a
full join a b on a.t+1 = b.t
where strftime('%s',b.event_timestamp_kst) - strftime('%s',a.event_timestamp_kst) >= 3600
or b.event_timestamp_kst is null
or a.event_timestamp_kst is null )
select c.user_pseudo_id, c.ss session_start, b.ee session_end
from b
join b c on b.tt = c.tt+1
GPT가 작성한 정답
- 시간에서 이전 행(LAG(event_timestamp_kst) OVER (ORDER BY event_timestamp_kst))의 시간을 빼서 한시간 이상 차이가 난다면 1을 부여하고 아니라면 0을 부여한다. 이전 행이 Null이어도 1을 부여
- 이 값들을 윈도우 함수 sum() over를 이용하여 누적합을 구한다
// 처음 행부터 지금 행까지
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
- 누적합으로 만들 수 있는 그룹을 만들어 최소값 - 세션 시작, 최대값 - 세션 종료를 구한다.
WITH ordered_events AS (
SELECT
event_timestamp_kst,
LAG(event_timestamp_kst) OVER (ORDER BY event_timestamp_kst) AS prev_event_ts,
CASE
WHEN strftime('%s', event_timestamp_kst) - strftime('%s', LAG(event_timestamp_kst) OVER (ORDER BY event_timestamp_kst)) > 3600
OR LAG(event_timestamp_kst) OVER (ORDER BY event_timestamp_kst) IS NULL
THEN 1 ELSE 0
END AS is_new_session,
user_pseudo_id
FROM ga
WHERE user_pseudo_id = 'S3WDQCqLpK'
),
sessionized AS (
SELECT
*,
SUM(is_new_session) OVER (ORDER BY event_timestamp_kst ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS session_num
FROM ordered_events
),
session_ranges AS (
SELECT
user_pseudo_id,
session_num,
MIN(event_timestamp_kst) AS session_start,
MAX(event_timestamp_kst) AS session_end
FROM sessionized
GROUP BY user_pseudo_id, session_num
)
SELECT
user_pseudo_id,
session_start,
session_end
FROM session_ranges
ORDER BY session_start;
LAG() - 현재 행 기준으로 이전 행의 값을 가져옴.
LEAD() - 현재 행 기준으로 다음 행의 값을 가져옴.
• 이전/다음 시각과 비교해서 시간 차 계산할 때
• 세션 분리 기준 찾을 때 (현재 시간 - 이전 시간 >= 30분)
• 앞뒤 값을 기반으로 변화 감지할 때 (예: 주가 변화, 상태 변화 등)
LAG(column_name, offset, default_value) OVER (PARTITION BY ... ORDER BY ...)
• column_name: 이전 값을 가져올 컬럼
• offset: 몇 번째 이전 값? (생략 시 기본은 1)
• default_value: 이전 값이 없을 경우 대체할 값 (예: 첫 번째 행)
LEAD(column_name, offset, default_value) OVER (PARTITION BY ... ORDER BY ...)
• column_name: 다음 값을 가져올 컬럼
• offset: 몇 번째 다음 값? (생략 시 기본은 1)
• default_value: 다음 값이 없을 경우 대체할 값 (예: 첫 번째 행)
Share article