Twice Over

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
General Assembly

Problem

Every training run our ML platform kicks off lands as a row in ml_models, and the registry's health check expects no model to hold more than 20 runs once failed attempts are set aside, since anything above that usually means runs are being registered twice over. Report the models that break that expectation, along with how many runs each one racked up.

Same model, trained twice.

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 4 of 4 rows
mdl_namerun_count
churn_pred26
demand_fcst24
fraud_detect24
img_classify26

Worked solution and explanation

What this problem is really about

Underneath the registry health check this is a two-stage filter, and the whole test is knowing which stage each condition lives in. The expectation is a cap: no model should hold more than twenty live runs, and the report is the models that break it. Dropping the failed runs happens row by row, before anything is grouped, so it belongs in WHERE. Testing the cap happens after the rows collapse into per-model totals, so it can only live in HAVING. Swap them and it breaks: write WHERE COUNT(*) > 20 and the query errors, because the count does not exist yet when WHERE runs. Skip the failed-run filter and all eight models fail the check. The subtler miss is COUNT(DISTINCT version), which erases the very repeats the check exists to catch and reports nothing.


Working through it

Step 1: Drop the failed runs first

WHERE status <> 'failed' removes the runs that never produced a model, row by row, before any grouping happens. This is a row-level test, so it sits in WHERE. Leave it out and failed attempts pad every model's total, so models that never really trained that often get flagged as violators.

Step 2: Group by the model, count every run

Each row in ml_models is one training run, so a model registered over and over shows up as many rows sharing one mdl_name. GROUP BY mdl_name with COUNT(*) counts those runs. Reaching for COUNT(DISTINCT version) collapses the exact repeats you are hunting for.

Step 3: Test the cap with HAVING

HAVING COUNT(*) > 20 is the expectation itself: it keeps only the models over the cap, which is exactly the list the health check reports. That count does not exist until after GROUP BY, so the condition cannot sit in WHERE.


The solution

Models over the twenty-run cap
SELECT mdl_name, COUNT(*) AS run_count
FROM ml_models
WHERE status <> 'failed'
GROUP BY mdl_name
HAVING COUNT(*) > 20

Common follow-up questions