Past the Threshold

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
L3
Asked in
Google

Problem

Our retention analyst calls a user engaged once they have more than 3 sessions in user_sessions: which users qualify, and how many sessions does each one have?

Somewhere after the third visit, a habit quietly forms. Find the ones who crossed over.

Tables

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

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

Expected output

First 5 of 20 rows
user_idsession_count
1008
1975
2945
3915
4885

Worked solution and explanation

This is a per-user threshold dressed up as a retention metric. The cutoff belongs to a user's whole history, not to any one session, so no row in user_sessions can tell you whether its owner qualifies: the count has to exist first, and the filter has to run on it. Everyone writes the count. What separates candidates is where the cutoff lands and what gets counted. Put it on the rows and the query errors or filters the wrong thing. Count device_id instead of sessions and four engaged users silently vanish. Read 'more than 3' as 'at least 3' and the list grows from 20 users to 48.

Getting to the answer

Step 1: Stay inside user_sessions

Every piece of the answer, user_id and the sessions themselves, lives in user_sessions. The users table is a temptation: joining it adds a second scan and changes no row of the result, because the session's user_id already identifies the user.

Step 2: Count sessions, not a column

COUNT(*) counts rows, and each row is a session. COUNT(device_id) counts non-NULL devices, and 23 sessions have no device recorded. User 876 has five sessions, three of them without a device, so the column count reports 2 and pushes them below the cutoff.

Step 3: Filter the count once it exists

The condition is about each user's total, so it goes in HAVING, which runs once per group after COUNT(*) is computed. WHERE runs per session before any grouping and cannot see the count; most engines reject WHERE COUNT(*) > 3 outright.

Engaged users and their session counts
SELECT user_id, COUNT(*) AS session_count
FROM user_sessions
GROUP BY user_id
HAVING COUNT(*) > 3
Counting rows
COUNT(*): user 876 has 5 sessions and qualifies, and user 100 has 8. Twenty users clear the bar.
Counting a column
COUNT(device_id): NULL devices are skipped, so 876 drops to 2 and 100 to 6. Four of the twenty engaged users disappear without any error.

Common follow-up questions