Streamhub's product team wants every session compared against that user's very first session.
Write a query to return every session's ID, user ID, event count, and the event count from that same user's first session chronologically.
Assumptions:
- The
sessionstable has one row per session with anid, auser_id, anevent_count, and astarted_attimestamp. - A user's first session is the session with the smallest
started_atfor thatuser_id. The same first-session event count appears on every row sharing auser_id. - The final result is sorted by
user_idascending, then bystarted_atascending.
Output:
- One row per session, with columns
id,user_id,event_count, andfirst_session_events. Sorted byuser_id, thenstarted_at.
Schema · analytics 5 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
SELECT
id,
user_id,
event_count,
FIRST_VALUE(event_count) OVER (
PARTITION BY
user_id
ORDER BY
started_at
) AS first_session_events
FROM
sessions
ORDER BY
user_id,
started_at The shape
The "anchor from history" pattern: every record carries the partition's earliest value alongside its own. FIRST_VALUE(event_count) looks up the value at position 1 of each user's chronologically-ordered sessions and attaches that single number to every row in the user's window. The analyst can now read each session's event count and the user's first-session event count side by side, on the same row.
Clause by clause
SELECT id, user_id, event_count, FIRST_VALUE(event_count) OVER (PARTITION BY user_id ORDER BY started_at) AS first_session_eventsreturns each session's identifying columns plus the user's first-session event count.PARTITION BY user_idcarves the table into one window per user;ORDER BY started_atdefines the chronological order inside that window;FIRST_VALUEpulls back the event count at position 1.FROM sessionsreads every session.ORDER BY user_id, started_atsorts the printed result chronologically within each user so the partition reads top to bottom in time order.
The trap
The default frame of a window function with ORDER BY is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. That default does not bite FIRST_VALUE, because position 1 of the partition is in every running frame from the very first row onward. FIRST_VALUE returns the same value on every row whether the frame is explicit or default. LAST_VALUE and NTH_VALUE behave differently and need an explicit full-partition frame; FIRST_VALUE does not.
You practiced FIRST_VALUE for an anchor-from-history pattern — every record carries the partition's earliest value alongside its own.