Where We Left Off
A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- medium
- Seniority
- junior
Problem
We run a subscription app, and a user can start many sessions over their lifetime. Before a support call, the agent needs the page count from each user's most recent session, listed by user.
Every user has a last visit on file. Surface the state you last saw them in.
Tables
user_sessions
Columns: session_id INTEGER, user_id INTEGER, device_id INTEGER, session_start TEXT, session_duration_sec INTEGER, pages_viewed INTEGER
| session_id | user_id | device_id | session_start | session_duration_sec | pages_viewed |
|---|---|---|---|---|---|
| 7061 | 197 | 230 | 2026-02-02 01:00:00 | 53 | 3 |
| 7122 | 294 | 259 | 2026-03-03 02:00:00 | 76 | 6 |
| 7183 | 391 | 288 | 2026-04-04 03:00:00 | 99 | 9 |
| 7244 | 488 | 317 | 2026-05-05 04:00:00 | 122 | 12 |
| 7305 | 585 | 346 | 2026-06-06 05:00:00 | 145 | 15 |
| 7366 | 682 | 375 | 2026-07-07 06:00:00 | 168 | 18 |
| 7427 | 779 | 404 | 2026-08-08 07:00:00 | 191 | 21 |
| 7488 | 876 | NULL | 2026-09-09 08:00:00 | 214 | 24 |
| 7549 | 973 | 462 | 2026-01-10 09:00:00 | 237 | 27 |
| 7610 | 1070 | 491 | 2026-02-11 10:00:00 | 260 | 30 |
Expected output
| user_id | pages_viewed |
|---|---|
| 100 | 40 |
| 197 | 33 |
| 294 | 36 |
| 391 | 29 |
| 488 | 32 |
Worked solution and explanation
What this problem really is
This is greatest-n-per-group wearing a support-tooling costume. The real skill: from many sessions per user, pick exactly one row, the most recent, without dropping users or returning two rows when a user's timestamps tie. Plenty of people know to sort by time; the separator is doing it per user in a single pass and keeping precisely one row each. The classic wrong turn is computing MAX(session_start) per user and joining it back, which quietly returns two rows for any user whose latest two sessions share a timestamp, and rescans the table to do it.
Walk the requirements
Step 1: Establish the grain
One user owns many sessions. The output is one row per user, so every decision from here is 'within this user, which single session survives'. Lose sight of that and you either collapse users together or leak duplicates.
Step 2: Rank each user's sessions by recency
Number the sessions inside each user from newest to oldest. session_start sorts correctly as ISO text, so ordering it descending puts the latest session first. Add session_id descending as a tiebreak so two sessions stamped at the same instant still produce a deterministic winner.
Step 3: Keep the newest, then order the report
Filter to the top-ranked row per user, which is the number-one session, and select its pages_viewed. List the result by user_id so the report is stable and easy to scan.
The solution
WITH ranked AS (
SELECT user_id,
pages_viewed,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY session_start DESC, session_id DESC) AS rn
FROM user_sessions
)
SELECT user_id, pages_viewed
FROM ranked
WHERE rn = 1
ORDER BY user_idOne pass: rank within each user by recency, keep rank 1.
- `ROW_NUMBER` then filter
- One scan. Ranks the sessions inside each user, keeps rank 1, and a
session_idtiebreak forces a single winner. One row per user, guaranteed. - `MAX(session_start)` then join back
- Two passes over the table. Correct only when timestamps are unique per user; the moment two sessions tie, the user appears twice with different page counts.
Common follow-up questions
- Return the page count from each user's earliest session instead of their latest. (Tests flipping the ranking order to ascending and confirming the direction is the only thing that changes.)
- For each user, return both their first and last session's page counts in one row. (Forces two rankings (or conditional aggregation over the ranked set) and a single collapsed row per user.)
- Now do this per device rather than per user, and break ties on identical timestamps by the higher `session_id`. (Probes swapping the partition key and making the tiebreak an explicit, stated rule.)