Where Users Linger
An easy SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- easy
- Seniority
- L3
- Asked in
- Airbnb
Problem
An analyst sizing up mobile engagement counts only the sessions in user_sessions whose device appears in devices with a mobile device type, crediting each session to that device's operating system. Among those sessions, return the one operating system with the longest average session duration, together with that average.
Attention is the scarcest resource. Find the platform that holds it longest.
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 |
devices
Columns: device_id INTEGER, device_type TEXT, os_name TEXT, os_version TEXT, browser TEXT
| device_id | device_type | os_name | os_version | browser |
|---|---|---|---|---|
| 201 | desktop | Android | 15.1 | Chrome |
| 230 | tablet | Windows | 16.2 | Firefox |
| 259 | smart_tv | macOS | 17.0 | Edge |
| 288 | wearable | Linux | 11 | Opera |
| 317 | mobile | tvOS | 12 | Samsung Internet |
| 346 | desktop | watchOS | 13 | NULL |
| 375 | tablet | iOS | 10.0.19041 | Safari |
| 404 | smart_tv | Android | 14.1 | Chrome |
| 433 | wearable | Windows | NULL | Firefox |
| 462 | mobile | macOS | 14.0 | Edge |
Expected output
| os_name | avg_duration |
|---|---|
| macOS | 1759 |
Worked solution and explanation
Why this problem exists in real interviews
This is a filtered top-1 dressed up as an engagement question. Anyone can write the join, the AVG and the LIMIT 1. The trap is the cohort: mobile is a column, device_type, not a guess about which os_name values sound like phones. Filter on os_name IN ('iOS','Android') and you drop the macOS rows this data files as mobile, which is exactly the OS that wins, so you hand back a plausible runner-up with a confident average.
Break down the requirements
Step 1: Confirm the mobile predicate
Ask aloud: is device_type = 'mobile' the cohort, or do we treat any os_name of iOS or Android as mobile? The brief says mobile device type, which is the device_type column. Lock it.
Step 2: Join user_sessions to devices
user_sessions us INNER JOIN devices d ON us.device_id = d.device_id. INNER is fine here: a session with no device row has no operating system to credit, so it is data quality noise, not a mobile session.
Step 3: Aggregate average duration
AVG(us.session_duration_sec) grouped by d.os_name. Average across sessions, not users, and versions roll up into one row per OS. Call that out so the interviewer knows you considered the alternative.
Step 4: Sort and cap to one row
ORDER BY avg_duration DESC LIMIT 1. The prompt says the one operating system, singular. Don't build a tie-handling rank unless they push.
The solution
SELECT d.os_name,
AVG(us.session_duration_sec) AS avg_duration
FROM user_sessions us
INNER JOIN devices d
ON us.device_id = d.device_id
WHERE d.device_type = 'mobile'
GROUP BY d.os_name
ORDER BY avg_duration DESC
LIMIT 1COMMON FOLLOW-UP QUESTIONS
Common follow-up questions
- How would the query change if a single device could have its `os_name` updated over time? (Probes whether you'd want an SCD2 device dimension or accept current-state attribution.)
- What if we want average minutes per user per OS instead of per session? (Tests whether you can switch grain from session to user with a nested aggregation.)
- Last 30 days only, given the partition on `session_start`, what changes? (Checks that you add `WHERE us.session_start >= CURRENT_DATE - INTERVAL '30 days'` to prune partitions.)
- How do you handle sessions with NULL `device_id`? (Probes your INNER vs LEFT JOIN reasoning and whether you'd surface orphan rates to the PM.)