iOS Sessions by Device Type

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

Each session in user_sessions records only a device_id, while the device's type and operating system are stored in devices. Count the sessions that came from mobile devices, broken down by operating system.

iOS engagement, device by device.

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

devices

Columns: device_id INTEGER, device_type TEXT, os_name TEXT, os_version TEXT, browser TEXT

devices: 10 of 200 rows
device_iddevice_typeos_nameos_versionbrowser
201desktopAndroid15.1Chrome
230tabletWindows16.2Firefox
259smart_tvmacOS17.0Edge
288wearableLinux11Opera
317mobiletvOS12Samsung Internet
346desktopwatchOS13NULL
375tabletiOS10.0.19041Safari
404smart_tvAndroid14.1Chrome
433wearableWindowsNULLFirefox
462mobilemacOS14.0Edge

Expected output

First 5 of 7 rows
os_namesession_count
Android6
Linux5
Windows5
iOS4
macOS5

Worked solution and explanation

This is a fact-to-dimension filter dressed up as a usage report. The thing you count, sessions, lives in user_sessions. The attribute that decides which sessions qualify (device_type) and the label you report them under (os_name) both live in devices. Everyone sees that a join is needed. The trap is answering from the wrong side of it: count rows in devices and you get the mobile device population per operating system, not the sessions those devices started. A phone with four sessions collapses to one, and Android comes out at 3 when the seed holds 6.

Walk the grain

Step 1: Decide what one counted row is

The answer counts sessions, so every counted row must be a user_sessions row. devices is there to label and filter, never to be counted. Saying 'one row per session, tagged with its device' out loud before typing is most of the problem.

Step 2: Attach each session to its device

Join user_sessions to devices on device_id. device_id is unique in devices, so the join cannot multiply sessions. The sessions with a NULL device_id find no partner and drop out, which is right: nothing ties them to a mobile device.

Step 3: Keep mobile, then count per operating system

Put device_type = 'mobile' in WHERE so it removes rows before anything is counted, then group by os_name and count session_id. Seven operating systems come back, and together they account for the 35 mobile sessions.

Mobile sessions per operating system
SELECT d.os_name, COUNT(s.session_id) AS session_count
FROM user_sessions AS s
JOIN devices AS d ON s.device_id = d.device_id
WHERE d.device_type = 'mobile'
GROUP BY d.os_name
The tempting shortcut
SELECT os_name, COUNT(*) AS session_count
FROM devices
WHERE device_type = 'mobile'
GROUP BY os_name

Runs cleanly and answers a different question: how many mobile devices each OS has.

Counting devices
COUNT(*) over devices gives 20 mobile devices spread across the seven operating systems: 3 for Android, 2 for iOS. It never reads user_sessions, so how often a device was used cannot show up.
Counting sessions
COUNT(s.session_id) after the join gives 35 sessions: 6 for Android, 4 for iOS. Each device contributes once per session it started, which is the number a usage report means.

Common follow-up questions