Both Arms of the Trial

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
Asked in
Meta

Problem

Our experimentation platform logs one record per user assignment, tagged with the feature test and the variant the user landed in. Find the tests that routed more assignments to 'variant_a' than to 'variant_b'.

Some features were tried both ways.

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

Expected output

First 3 of 3 rows
exp_name
new_feed_algo
notif_freq
pricing_tier

Worked solution and explanation

What this problem really is

This is a comparison of two subpopulations inside one group, wearing an experiment-tracking costume. For each test the real question is simple: did more assignments land in 'variant_a' than in 'variant_b'? On this data every test ran both arms, so anyone who reaches for WHERE variant = 'variant_a' has already deleted every variant_b row and can no longer compare the two arms at all. The move that works is to keep all of a test's rows inside the group and count each variant separately, then compare those two counts. Get it wrong and you either return nothing, or you fall back to raw row totals and flag tests that were never actually skewed toward variant_a.

WHERE (wrong)
WHERE variant = 'variant_a' throws away every variant_b row before grouping, so within a test there is no variant_b left to compare against. You can count one arm but never weigh it against the other.
Conditional counts (right)
Keep all rows in the group and use SUM(CASE WHEN ...) per variant. Both arms' rows stay in the group, so HAVING can compare the two counts directly.

Building it step by step

Step 1: Group by the test

GROUP BY exp_name collapses all assignment records for a test into a single row, so the two-arm comparison is asked once per test.

Step 2: Count each arm conditionally

SUM(CASE WHEN variant = 'variant_a' THEN 1 ELSE 0 END) counts the variant_a assignments in each group, and the same expression for variant_b counts its assignments. Rows of other variants (variant_c, holdout, control) contribute 0 to both and drop out of the comparison. Note this counts assignment records, so a user assigned twice counts twice.

Step 3: Compare the two counts

HAVING the variant_a count > the variant_b count keeps only the tests skewed toward variant_a. An even split (equal counts) is excluded by the strict greater-than. Return exp_name and order it alphabetically.

The solution

Conditional counts compared in HAVING
SELECT exp_name
FROM experiments
GROUP BY exp_name
HAVING SUM(CASE WHEN variant = 'variant_a' THEN 1 ELSE 0 END) > SUM(CASE WHEN variant = 'variant_b' THEN 1 ELSE 0 END)

Common follow-up questions