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.

Advanced business practice

Sign up free to try it on a real business scenario