Satisfaction by Platform

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
Walmart

Problem

Give us the average experiment outcome score for the 25-34 age cohort on each platform, with platforms told apart by their labels exactly as our event logs captured them, a missing label included. Our scoring rubric credits only the whole points of each logged outcome, so drop each score's fraction before averaging, and report the average rounded to the nearest whole number.

Satisfaction scores, platform by platform.

Tables

experiments

Columns: exp_id INTEGER, exp_name TEXT, variant TEXT, user_id INTEGER, outcome REAL, created TEXT, platform TEXT

experiments: 10 of 200 rows
exp_idexp_namevariantuser_idoutcomecreatedplatform
1053checkout_v3variant_a10011.32026-02-02android
1106onboard_flowvariant_b19722.62026-03-03web
1159pricing_tiervariant_c29433.92026-04-04iOS
1212search_rankholdout39145.22026-05-05Android
1265rec_model_bcontrol48856.52026-06-06NULL
1318notif_freqvariant_a585NULL2026-07-07WEB
1371home_layoutvariant_b68279.12026-08-08NULL
1424new_feed_algovariant_c77990.42026-09-09ios
1477checkout_v3holdout8761.72026-01-10android
1530onboard_flowcontrol973132026-02-11web

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 7 rows
platformavg_outcome_score
NULL40
Android39
WEB48
android28
iOS52

Worked solution and explanation

What this really is

Strip the growth framing and this is a filtered group-average across two tables with one conversion hidden in the order of operations. The score and the label live in experiments, the cohort lives in users.age_bucket, so the join exists only to carry the cohort onto the rows you average. Everyone gets the join. What separates candidates is where the whole-point conversion goes: it has to hit each score before AVG, not the average after it. Put it last and 'Android' reports 40 and 'WEB' reports 49, where the rubric says 39 and 48.


Build it in four moves

Step 1: Bring age_bucket next to the score

Join experiments to users on user_id. An inner join is right: an event only matters if its user can be placed in an age bucket, and users with no matching row have no cohort to belong to.

Step 2: Keep only the 25-34 cohort

Filter u.age_bucket = '25-34' in the WHERE. It runs before the grouping, so it shrinks the set you aggregate, which is also the cheaper plan.

Step 3: Drop each score's fraction before averaging

CAST(e.outcome AS INTEGER) truncates toward zero, so 48.6 becomes 48. A NULL outcome stays NULL through the cast, and AVG skips it, so missing scores never dilute a platform. Every score on this data is positive, which means FLOOR would land on the same values.

Step 4: Average per raw label, then round

Group on e.platform exactly as stored and take ROUND(AVG(...)) over the whole points. For 'android' the scores 11 and 44 average to 27.5, which rounds to 28.

Whole-point average per platform for the 25-34 cohort
SELECT e.platform, ROUND(AVG(CAST(e.outcome AS INTEGER))) AS avg_outcome_score
FROM experiments e
INNER JOIN users u ON e.user_id = u.user_id
WHERE u.age_bucket = '25-34'
GROUP BY e.platform

The cast sits inside the average and the round sits outside it.

Round the raw average
ROUND(AVG(e.outcome)) averages 'Android' to 39.6 and rounds up to 40, and averages 'WEB' to 48.6 and rounds up to 49. The fraction the rubric never awarded pushes both over the line.
Average the whole points
ROUND(AVG(CAST(e.outcome AS INTEGER))) averages 39 and 48 for those two labels. The 0.6 is gone before the mean is taken, so it cannot round anything up.

Common follow-up questions