Session Count Distribution

A hard SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
hard
Seniority
L4
Asked in
Meta

Problem

Among the users who signed up in 2024 or 2025, how many logged exactly one session in user_sessions during 2026, how many logged exactly two, and so on up the scale? The breakdown reads from the smallest session count to the largest.

How are sessions distributed among the newest users?

Tables

users

Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT

users: 10 of 200 rows
user_idusernameemailsignup_dateaccount_statusage_bucket
100alicealice@example.com2025-02-02inactive25-34
197aaron42aaron42@example.com2026-03-03suspended35-44
294 ameliaamelia@example.com2024-04-04pending_verification45-54
391arjun arjun@example.com2025-05-05active55-64
488ava99ava99@example.com2026-06-06inactive65+
585andrew_kandrew_k@example.com2024-07-07suspendedNULL
682anikaanika@example.com2025-08-08 16:34:00pending_verification18-24
779aidenaiden@example.com2026-09-09 14:53:00active25-34
876aria_baria_b@example.com2024-10-10inactive35-44
973brianbrian@example.com2025-11-11suspended45-54

user_sessions

Columns: session_id INTEGER, user_id INTEGER, device_id INTEGER, session_start TEXT, session_duration_sec INTEGER, pages_viewed INTEGER

user_sessions: 10 of 200 rows
session_iduser_iddevice_idsession_startsession_duration_secpages_viewed
70611972302026-02-02 01:00:00533
71222942592026-03-03 02:00:00766
71833912882026-04-04 03:00:00999
72444883172026-05-05 04:00:0012212
73055853462026-06-06 05:00:0014515
73666823752026-07-07 06:00:0016818
74277794042026-08-08 07:00:0019121
7488876NULL2026-09-09 08:00:0021424
75499734622026-01-10 09:00:0023727
761010704912026-02-11 10:00:0026030

Expected output

First 4 of 4 rows
session_countuser_count
17
25
512
81

Worked solution and explanation

This is a count of counts

Strip off the analytics costume and this is a two-level aggregation: a distribution of a value that does not exist yet. The bucket key is each user's own session count, and no column holds it until you have already grouped once. Anyone can count sessions per user. The move that separates candidates is realizing you then have to group AGAIN, this time by that computed count. Miss it and you write one flat grouping that answers a different question. The second trap is quieter: apply the signup window loosely and users who joined outside 2024 and 2025 keep contributing, quietly inflating every bucket.


Build it in stages

Step 1: Fence the cohort first

Restrict users to the cohort with signup_date BETWEEN '2024-01-01' AND '2025-12-31'. This is not decoration: on this data, users who joined outside those two years still logged sessions in 2026, so skipping it pushes the one-session bucket from 7 up to 11. Apply it before you count, not after.

Step 2: Collapse to one row per user

Join the cohort to user_sessions, keep only rows where strftime('%Y', session_start) = '2026', and GROUP BY user_id with COUNT(*). Now every qualifying user is one row holding their 2026 session total. Users with zero 2026 sessions simply never appear here, which is exactly why no 0 bucket is fabricated later.

Step 3: Aggregate the counts themselves

Take that per-user result and GROUP BY session_count, counting the users at each value. Order ascending so the distribution reads from the quietest users to the most engaged.

Count of counts over a filtered cohort
WITH cohort AS (
    SELECT user_id
    FROM users
    WHERE signup_date BETWEEN '2024-01-01' AND '2025-12-31'
),
sessions_per_user AS (
    SELECT s.user_id, COUNT(*) AS session_count
    FROM user_sessions s
    INNER JOIN cohort c ON s.user_id = c.user_id
    WHERE strftime('%Y', s.session_start) = '2026'
    GROUP BY s.user_id
)
SELECT session_count, COUNT(*) AS user_count
FROM sessions_per_user
GROUP BY session_count
ORDER BY session_count ASC
One flat grouping (wrong)
GROUP BY user_id, COUNT(*) and stop. That gives you a per-user list, not a distribution. Or worse, GROUP BY some session column and lose the per-user step entirely. Either way you never answer 'how many users had exactly N sessions'.
Count of counts (right)
Group once to get each user's count, then group that result by the count value. The distribution's key is manufactured by the first aggregation and consumed by the second.

Common follow-up questions