Higher Performing Variant

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
Airbnb

Problem

Several clients logged their variant labels in ab_results with their own capitalization. Before those labels are reconciled, an analyst wants to know which label, as logged, has the highest average metric value across every test. Return that one label with its average, rounded to two decimal places.

Control versus treatment. One wins.

Tables

ab_results

Columns: result_id INTEGER, test_name TEXT, variant TEXT, user_id INTEGER, metric TEXT, value REAL, created TEXT

ab_results: 10 of 200 rows
result_idtest_namevariantuser_idmetricvaluecreated
237new_homepagetreatment_a100click_rate13.72026-02-02
274pricing_pagetreatment_b197revenue27.42026-03-03
311onboarding_v3Control294bounce41.12026-04-04
348search_algo_bCONTROL391time_on_page54.82026-05-05
385rec_engine_v2control488signup68.52026-06-06
422checkout_flow_v2treatment_a585conv_rate82.22026-07-07
459new_homepagetreatment_b682click_rate95.92026-08-08
496pricing_pageControl779revenue9.62026-09-09
533onboarding_v3CONTROL876bounce23.32026-01-10
570search_algo_bcontrol973time_on_pageNULL2026-02-11

Expected output

First 1 of 1 rows
variantavg_value
CONTROL50.55

Worked solution and explanation

This is a pick-the-best-group-by-its-mean problem dressed up as an experiment readout. Averaging per label is the easy half. What separates candidates is returning exactly one row, the label with the highest mean, and leaving the labels as logged. The five arms sit within six points of each other (45.00 to 50.55), so every shortcut crowns a different winner. Merge the three spellings of control and that arm drops to 47.96, which hands the crown to the first treatment arm at 49.45. Pick by the single biggest reading and the same arm wins on a 98.7. Only comparing the per-label means returns CONTROL at 50.55.

Walking it

Step 1: Keep the logged label as the grain

Group ab_results on variant alone. Tests and metrics pool together, which is what the readout asks for, and 'Control', 'CONTROL' and 'control' stay three arms because the analyst wants the labels before anyone reconciles them.

Step 2: Average, and let AVG skip the blanks

AVG(value) divides by the rows that actually hold a value, so the 20 empty readings (all on lowercase 'control') drop out instead of dragging that arm down to 22.50. Round in the same expression so avg_value is the number the reader sees.

Step 3: Sort the means and keep the top one

ORDER BY avg_value DESC LIMIT 1 collapses five rows to one. The top two means are 50.55 and 49.45, so the cut never falls between tied rows and no tiebreaker is owed.

The label with the highest mean
SELECT variant, ROUND(AVG(value), 2) AS avg_value
FROM ab_results
GROUP BY variant
ORDER BY avg_value DESC
LIMIT 1

One scan, five groups, one row back.

Labels merged
Grouping on LOWER(variant) folds three control spellings into one arm averaging 47.96, and the first treatment arm wins at 49.45. That is a correct answer to a question nobody asked yet.
Labels as logged
Grouping on variant keeps five arms. CONTROL leads at 50.55 and is the one row returned.

Common follow-up questions