The Ones Who Finish

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
mid
Asked in
DoorDash

Problem

A fitness streaming app measures engagement by how far members get through each clip before dropping off, comparing time watched against the clip's full length. For views logged this year, find the average completion and the number of views per content format, ignoring items with no recorded length.

Plenty of members press play. Far fewer reach the final rep. Find the formats that hold them.

Tables

content_views

Columns: view_id INTEGER, content_id INTEGER, user_id INTEGER, viewed_at TEXT, watch_seconds INTEGER, device_id 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

content_items

Columns: content_id INTEGER, title TEXT, content_type TEXT, duration_seconds INTEGER, creator_id INTEGER, publish_date TEXT

content_items: 10 of 200 rows
content_idtitlecontent_typeduration_secondscreator_idpublish_date
243The Ultimate Guide to AI TrendsarticleNULL1972026-02-02
286Top 10 Mobile Appspodcast1542942025-03-03
329Understanding Machine Learning [DRAFT]short2013912026-04-04
372Mastering Tech Startupslivestream2484882025-05-05
415Introduction to Cybersecurityvideo2955852026-06-06
458Deep Dive: Cloud ComputingarticleNULL6822025-07-07
501Behind the Scenes of Product Managementpodcast3897792026-08-08
544Breaking Down DevOpsshort4368762025-09-09
587Exploring Web Developmentlivestream483NULL2026-01-10
630How to Data Sciencevideo53010702025-11-11

Expected output

First 4 of 4 rows
content_formatavg_completion_rateview_count
livestream0.98625
podcast1.34422
short1.14323
video1.04925

Worked solution and explanation

Why this problem exists in real interviews

This looks like an engagement report, but it is really a grain-and-ratio question wearing a fitness costume. The metric lives in content_views (watch_seconds) while the denominator lives in content_items (duration_seconds), so you cannot compute completion until you join, and once joined the only honest unit is one ratio per view. The trap is what 'average completion' means: do you average the per-view ratios, or do you divide total watch by total length? Those are different numbers, and picking the wrong one silently lets a few long clips dominate the format's score.


Break down the requirements

Step 1: Attach each view to its clip

watch_seconds has no meaning without the clip length next to it, so join content_views to content_items on content_id. After the join every row is one view that knows both how long the member watched and how long the clip runs.

Step 2: Scope to this year and guard the denominator

strftime('%Y', cv.viewed_at) = '2026' keeps the current era. duration_seconds > 0 is the 'ignoring items with no recorded length' clause made literal: an article or a zero-length item would make watch_seconds / duration_seconds divide by zero and surface as a stray null format, and dropping those rows is the correct reading since a clip with no length has no completion to measure.

Step 3: Average the per-view ratio, by format, and count the views

GROUP BY content_type, then AVG(watch_seconds * 1.0 / duration_seconds) for the metric and COUNT(*) for how many views backed it. The * 1.0 forces real division; without it integer math floors most ratios to 0. Order by that average descending so the format that holds attention sits on top.


The solution

Average completion by format
SELECT ci.content_type AS content_format,
       ROUND(AVG(cv.watch_seconds * 1.0 / ci.duration_seconds), 3) AS avg_completion_rate,
       COUNT(*) AS view_count
FROM content_views cv
JOIN content_items ci ON cv.content_id = ci.content_id
WHERE strftime('%Y', cv.viewed_at) = '2026'
  AND ci.duration_seconds > 0
GROUP BY ci.content_type

Common follow-up questions