The Screens They Carry
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
- L4
- Asked in
- Airbnb
Problem
Each user_sessions row records which device a user was on, with the user's age group kept in users and the device's type in devices. Count the unique devices the 25-34 age group has used, by device type, from most to fewest, with equal counts listed alphabetically by type.
One age cohort, and every kind of screen it reaches for.
Tables
users
Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT
| user_id | username | signup_date | account_status | age_bucket | |
|---|---|---|---|---|---|
| 100 | alice | alice@example.com | 2025-02-02 | inactive | 25-34 |
| 197 | aaron42 | aaron42@example.com | 2026-03-03 | suspended | 35-44 |
| 294 | amelia | amelia@example.com | 2024-04-04 | pending_verification | 45-54 |
| 391 | arjun | arjun@example.com | 2025-05-05 | active | 55-64 |
| 488 | ava99 | ava99@example.com | 2026-06-06 | inactive | 65+ |
| 585 | andrew_k | andrew_k@example.com | 2024-07-07 | suspended | NULL |
| 682 | anika | anika@example.com | 2025-08-08 16:34:00 | pending_verification | 18-24 |
| 779 | aiden | aiden@example.com | 2026-09-09 14:53:00 | active | 25-34 |
| 876 | aria_b | aria_b@example.com | 2024-10-10 | inactive | 35-44 |
| 973 | brian | brian@example.com | 2025-11-11 | suspended | 45-54 |
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 |
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
| device_type | device_count |
|---|---|
| smart_tv | 9 |
| mobile | 5 |
| desktop | 4 |
| tablet | 4 |
| wearable | 2 |
Worked solution and explanation
What this really is
Beneath the device-diversity framing, this is a fan-in with a dedup at the far end. A user has many sessions, each session points at exactly one device, and the same device reappears across many sessions. The skill being probed: can you walk the bridge from users through user_sessions to devices, then collapse the fan-out so each physical device is counted once? Anyone can write the three joins. The trap is the aggregate: COUNT(*) counts session rows, not devices, and since one popular device generates many sessions it silently inflates every device_type. COUNT(DISTINCT device_id) is the whole game.
Walking the chain
Step 1: Scope the cohort
WHERE u.age_bucket = '25-34' scopes the population to the cohort of interest before any counting. Applying it on the users table keeps the filter cheap and lets the optimizer prune early.
Step 2: Join through the bridge
There is no direct users-to-devices link. Go users -> user_sessions on user_id, then user_sessions -> devices on device_id. The session table is the bridge that ties a person to the hardware they actually used; skipping it has no join key to stand on.
Step 3: Dedup as you count
GROUP BY d.device_type with COUNT(DISTINCT d.device_id) buckets the surviving rows by kind of device and dedups within each bucket, so a device used in fifty sessions still counts as one. ORDER BY device_count DESC, device_type puts the most-used kinds on top and lists equal counts alphabetically.
The solution
SELECT d.device_type, COUNT(DISTINCT d.device_id) AS device_count
FROM users u
JOIN user_sessions us ON u.user_id = us.user_id
JOIN devices d ON us.device_id = d.device_id
WHERE u.age_bucket = '25-34'
GROUP BY d.device_type
ORDER BY device_count DESC, device_typeCommon follow-up questions
- How would you produce this for every age bucket at once? (Drop the `age_bucket` predicate and add `age_bucket` to the `GROUP BY` to get a per-bucket breakdown.)
- How would you show each type's share of the total? (Wrap the count: `100.0 * COUNT(DISTINCT d.device_id) / SUM(COUNT(DISTINCT d.device_id)) OVER ()`.)
- What changes if one device can belong to more than one user? (`COUNT(DISTINCT device_id)` already handles it: a device shared across users is still one device.)