Median Model Accuracy

A hard SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
hard
Seniority
L5
Asked in
City and County of San Francisco

Problem

Compute the median accuracy for each model (mdl_name). When a model has an even number of records, average the two middle values. Ignore records where accuracy is null. Return results ordered alphabetically by model name.

The median accuracy. Not the mean.

Tables

ml_models

Columns: model_id INTEGER, mdl_name TEXT, version TEXT, accuracy REAL, status TEXT, train_at TEXT, framework TEXT

ml_models: 10 of 200 rows
model_idmdl_nameversionaccuracystatustrain_atframework
123rec_enginev1.10.72training2026-02-02 01:00:00TensorFlow
146churn_predv2.00.89archived2026-03-03 02:00:00XGBoost
169spam_filter3.00.61failed2026-04-04 03:00:00sklearn
192img_classifyv2.1-beta0.78validating2026-05-05 04:00:00pytorch
215sentiment1.0.00.95Deployed2026-06-06 05:00:00tensorflow
238demand_fcstv1.00.67deployedNULLPyTorch
261price_optv1.10.84Training2026-08-08 07:00:00TensorFlow
284fraud_detectv2.0NULLarchived2026-09-09 08:00:00XGBoost
307rec_engine3.00.73failed2026-01-10 09:00:00sklearn
330churn_predv2.1-beta0.9validating2026-02-11 10:00:00pytorch

Expected output

First 5 of 7 rows
mdl_namemedian_accuracy
churn_pred0.93
demand_fcst0.725
img_classify0.84
price_opt0.895
rec_engine0.78

Worked solution and explanation

What this really is

Strip the costume and this is a hand-rolled median in a dialect that has no median. The engine this runs on ships no PERCENTILE_CONT and no MEDIAN, so the one-line answer errors out, and AVG(accuracy) runs but hands you the arithmetic mean, which on this skewed accuracy distribution is a different number than the middle value for every model. The real skill is emulating a parity-aware median by hand: number each model's rows by accuracy, size the group, then branch on parity: one middle row when the count is odd, the average of the two middle rows when it is even. The trap is that branch. Forget to gate the even case on parity and every odd-count model silently averages two adjacent values instead of returning its true middle.


Building it

Step 1: Drop the null-accuracy rows first

Filter accuracy IS NOT NULL inside the CTE, before any windowing. Do it later and the null rows still inflate cnt and shift rn, so the middle index points at the wrong row. fraud_detect carries a null accuracy here; leave it in and both that model's count and its center move.

Step 2: Number and size each model in parallel

ROW_NUMBER() OVER (PARTITION BY mdl_name ORDER BY accuracy) ranks each row within its model, lowest accuracy first. COUNT(*) OVER (PARTITION BY mdl_name) stamps the model's total onto every one of its rows. Same partition, two windows, one pass over the filtered set.

Step 3: Branch on parity to pick the middle

This is the crux. For an even count the two central positions are cnt / 2 and cnt / 2 + 1 under integer division; for an odd count the single center is (cnt + 1) / 2. Keep the branches mutually exclusive: (cnt % 2 = 0 AND rn IN (cnt / 2, cnt / 2 + 1)) OR (cnt % 2 = 1 AND rn = (cnt + 1) / 2). The cnt % 2 = 0 guard on the first branch is load-bearing.

Step 4: Average the survivors and order the result

Whatever rows survive, AVG(accuracy) is exactly right: one surviving row averages to itself, two average to their midpoint. GROUP BY mdl_name collapses each model to a single value, and ORDER BY mdl_name produces the alphabetical output.


The solution

Parity-aware median with parallel windows
WITH numbered AS (
    SELECT mdl_name, accuracy,
        ROW_NUMBER() OVER (PARTITION BY mdl_name ORDER BY accuracy) AS rn,
        COUNT(*) OVER (PARTITION BY mdl_name) AS cnt
    FROM ml_models
    WHERE accuracy IS NOT NULL
)
SELECT mdl_name,
    AVG(accuracy) AS median_accuracy
FROM numbered
WHERE (cnt % 2 = 0 AND rn IN (cnt / 2, cnt / 2 + 1))
    OR (cnt % 2 = 1 AND rn = (cnt + 1) / 2)
GROUP BY mdl_name
ORDER BY mdl_name
AVG(accuracy)
Runs everywhere, but it is the arithmetic mean. On the zipf-skewed accuracy values a handful of low runs drag it below the middle value, so it disagrees with the median for every model in the fleet.
Parity-aware median
The ROW_NUMBER and COUNT(*) windows plus the even/odd branch return the actual center value, robust to the outliers that AVG chases. This is the whole reason to hand-roll it.

Common follow-up questions