SQL Sessionization

Group individual events into visits — a new session starts whenever the gap since the last event is too long.

What & Why

Raw event logs don't come with a "session ID" — you build one by comparing each event's timestamp to the previous event's (via LAG), and starting a new session whenever the gap exceeds some threshold, like 30 minutes.

See How It Works

BUSINESS QUESTION

Combine feedback and feature-use activity, then keep events within 30 minutes in the same derived session.

iduser_idfeature_idratingnps_scorecommentcreated_at
1101159Clear and useful2024-01-25 12:15:00+00
210224NULLExport worked well2024-02-20 15:40:00+00
3103147Helpful setup flow2024-03-18 09:05:00+00
410433NULLNeeds clearer timing2024-04-08 17:30:00+00
idfeature_iduser_idused_atsession_id
700111012024-01-25 12:20:00+00sess_101a
700221022024-02-20 15:45:00+00sess_102a
700311032024-03-18 09:10:00+00sess_103a
700431042024-04-08 17:35:00+00sess_104a
EXAMPLE QUERY
WITH activity_events AS (
  SELECT id::bigint AS event_id, user_id, 'feedback' AS event_name, created_at
  FROM product.feedback
  UNION ALL
  SELECT id AS event_id, user_id, 'feature_used' AS event_name, used_at AS created_at
  FROM product.feature_usage
),
sequenced AS (
  SELECT
    *,
    LAG(created_at) OVER (PARTITION BY user_id ORDER BY created_at, event_id) AS previous_event_at
  FROM activity_events
),
boundaries AS (
  SELECT
    *,
    CASE
      WHEN previous_event_at IS NULL OR created_at - previous_event_at > INTERVAL '30 minutes' THEN 1
      ELSE 0
    END AS is_new_session
  FROM sequenced
)
SELECT
  event_id,
  user_id,
  event_name,
  created_at,
  SUM(is_new_session) OVER (PARTITION BY user_id ORDER BY created_at, event_id) AS derived_session_number
FROM boundaries
ORDER BY user_id, created_at, event_id;
RESULT — feedback and feature use grouped into sessions
event_iduser_idevent_namecreated_atderived_session_number
1101feedback2024-01-25 12:15:00+001
7001101feature_used2024-01-25 12:20:00+001
2102feedback2024-02-20 15:40:00+001
7002102feature_used2024-02-20 15:45:00+001
3103feedback2024-03-18 09:05:00+001
7003103feature_used2024-03-18 09:10:00+001
4104feedback2024-04-08 17:30:00+001
7004104feature_used2024-04-08 17:35:00+001

Each user's feature-use event occurs five minutes after feedback, so both rows remain inside derived session 1.

This lesson's practice is part of Pro.

Advanced business practice

Sign up free to try it on a real business scenario