The Apprentices Still in the Forge
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
Problem
The ML platform team is sizing a new training GPU cluster and needs to know how much of the catalog is still mid-flight, meaning models whose status is 'training'. Count the unique model names (mdl_name) in that state and return it as training_count.
A model is not a model until it stops learning and starts earning.
Tables
ml_models
Columns: model_id INTEGER, mdl_name TEXT, version TEXT, accuracy REAL, status TEXT, train_at TEXT, framework TEXT
| model_id | mdl_name | version | accuracy | status | train_at | framework |
|---|---|---|---|---|---|---|
| 123 | rec_engine | v1.1 | 0.72 | training | 2026-02-02 01:00:00 | TensorFlow |
| 146 | churn_pred | v2.0 | 0.89 | archived | 2026-03-03 02:00:00 | XGBoost |
| 169 | spam_filter | 3.0 | 0.61 | failed | 2026-04-04 03:00:00 | sklearn |
| 192 | img_classify | v2.1-beta | 0.78 | validating | 2026-05-05 04:00:00 | pytorch |
| 215 | sentiment | 1.0.0 | 0.95 | Deployed | 2026-06-06 05:00:00 | tensorflow |
| 238 | demand_fcst | v1.0 | 0.67 | deployed | NULL | PyTorch |
| 261 | price_opt | v1.1 | 0.84 | Training | 2026-08-08 07:00:00 | TensorFlow |
| 284 | fraud_detect | v2.0 | NULL | archived | 2026-09-09 08:00:00 | XGBoost |
| 307 | rec_engine | 3.0 | 0.73 | failed | 2026-01-10 09:00:00 | sklearn |
| 330 | churn_pred | v2.1-beta | 0.9 | validating | 2026-02-11 10:00:00 | pytorch |
Expected output
| training_count |
|---|
| 4 |
Worked solution and explanation
The real problem beneath the costume
Two things are hiding in plain sight. A single model ships as many rows, one per version, so counting rows counts releases, not models. And the status column was never normalized on write, so 'training', 'Training', and 'TRAINING' all live side by side. Match the raw string and you silently drop part of the fleet; count rows and you inflate a small backlog into a large one. Both mistakes send the wrong number to the people buying GPUs.
How to get there
Step 1: Normalize the filter first
LOWER(status) = 'training' folds every casing of the status into one match, so 'Training' and 'TRAINING' rows are not lost. Do this before you count, or the count is already wrong.
Step 2: Count models, not rows
COUNT(DISTINCT mdl_name) collapses the version rows down to one per model name. COUNT(*) here would answer a different question: how many training version rows exist, not how many models are training.
The solution
SELECT COUNT(DISTINCT mdl_name) AS training_count
FROM ml_models
WHERE LOWER(status) = 'training'- COUNT(*) (wrong)
- If
rec_enginehas three versions in training, this returns 3 for that one model. You end up sizing the cluster for phantom models. - COUNT(DISTINCT `mdl_name`) (right)
- The same three rows collapse to 1. You count the model once, which is what capacity planning actually needs.
Common follow-up questions
- What is the difference between COUNT(*) and COUNT(DISTINCT `mdl_name`) here? (Tests whether they understand rows-vs-entities counting.)
- How would you break the training count down per framework? (Add GROUP BY framework, still with the case-insensitive filter.)
- What if you only wanted models that entered training in the last 30 days? (Add a date predicate on `train_at`.)