Views by Specific Users

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

Problem

Only handles whose very first stored character is a lowercase 'a' belong to the spam wave, so a capitalized 'Alice' or a handle stored with a leading space is a different account. A trust-and-safety reviewer needs every row of content_views those accounts produced (alice, aaron42 and amelia among them), showing the view ID, content ID, timestamp and watch duration, oldest view first.

Retrieve all content views for a set of flagged user accounts

Tables

content_views

Columns: view_id INTEGER, content_id INTEGER, user_id INTEGER, device_id INTEGER, viewed_at TEXT, watch_seconds INTEGER

content_views: 10 of 200 rows
view_idcontent_iduser_iddevice_idviewed_atwatch_seconds
705337213614042026-02-02 01:07:0041
710650126226072026-03-03 02:14:0072
715963038838102026-04-04 03:21:00103
7212759514410132026-05-05 04:28:00134
7265888640512162026-06-06 05:35:00165
73181017766614192026-07-07 06:42:00196
73711146NULL16222026-08-08 07:49:00227
7424127548818252026-09-09 08:56:00258
747714041749NULL2026-01-10 09:03:00289
75301533301022312026-02-11 10:10:00320

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 14 rows
view_idcontent_idviewed_atwatch_seconds
100123166732022-04-17 16:52:00506
100123319742022-07-04 07:37:00971
1001236221782023-02-07 14:14:001932
100123083722024-08-09 08:56:00258
1001233912752025-03-12 15:33:001219

Worked solution and explanation

What this really is

This is a key-translation problem in a trust-and-safety costume. The reviewer hands you usernames, but content_views never stores a username. It keys every view by the surrogate user_id, and the only place a handle turns into an id is the users dimension. Everyone can write the projection and the sort. What separates candidates is resolving the handles through users before touching the fact table, instead of reaching for a username column that is not there or guessing ids. Guess wrong and you hand the investigator someone else's viewing history while the flagged accounts walk.

Getting there

Step 1: Find where the handle lives

Scan the schema before writing anything: content_views has user_id but no username. The handle exists only in users, so users is the translation table and the filter has to run against it.

Step 2: Join users to content_views on user_id

An inner join on u.user_id = cv.user_id attaches each view to its account. Views with a NULL user_id drop out, which is right: an anonymous view cannot belong to a flagged account.

Step 3: Filter on the handle's first stored character

SUBSTR(u.username, 1, 1) IN ('a') keeps every account whose handle starts with a lowercase 'a' exactly as stored. That is the reviewer's rule: a handle like 'Alice' or one stored with a leading space is a different account, so do not reach for LOWER or TRIM here. Writing it as a membership test means a second flagged letter is one more value in the list, not a new OR branch.

Step 4: Project the view columns, oldest first

Return only view_id, content_id, viewed_at and watch_seconds, and sort by viewed_at ascending so the reviewer reads the trail as it happened. Nothing from users belongs in the output.

Resolve handles through `users`, then pull the trail
SELECT
    cv.view_id,
    cv.content_id,
    cv.viewed_at,
    cv.watch_seconds
FROM content_views AS cv
JOIN users AS u
    ON u.user_id = cv.user_id
WHERE SUBSTR(u.username, 1, 1) IN ('a')
ORDER BY cv.viewed_at;

Common follow-up questions