Top 100 Batch Jobs Total Output
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
- L4
- Asked in
- Spotify
Problem
We're auditing throughput on a batch-processing platform and need the combined output of its ten busiest jobs, measured by rows completed. When jobs finish the same number of rows they share a position, so a tie at the tenth spot pulls every one of those jobs in. Return that single total.
The hundred biggest jobs. Combined output.
Tables
batch_jobs
Columns: job_id INTEGER, job_name TEXT, status TEXT, rows_done INTEGER, started TEXT, ended TEXT, priority INTEGER, retries INTEGER
| job_id | job_name | status | rows_done | started | ended | priority | retries |
|---|---|---|---|---|---|---|---|
| 1047 | user_export | running | 97 | 2026-02-02 01:00:00 | 2026-02-02 03:11:00 | 3 | 0 |
| 1094 | data_cleanup | failed | 194 | 2026-03-03 02:00:00 | 2026-03-03 04:22:00 | 6 | 0 |
| 1141 | email_blast | queued | 291 | 2026-04-04 03:00:00 | 2026-04-04 05:33:00 | 9 | 0 |
| 1188 | index_rebuild | canceled | 388 | 2026-05-05 04:00:00 | NULL | 2 | 0 |
| 1235 | cache_warm | Completed | 485 | 2026-06-06 05:00:00 | 2026-06-06 07:55:00 | 5 | 0 |
| 1282 | log_archive | FAILED | NULL | 2026-07-07 06:00:00 | 2026-07-07 08:06:00 | 8 | 0 |
| 1329 | metric_agg | completed | 679 | 2026-08-08 07:00:00 | 2026-08-08 09:17:00 | 1 | 0 |
| 1376 | backup_db | running | 776 | 2026-09-09 08:00:00 | NULL | 4 | 0 |
| 1423 | sync_elastic | failed | 873 | 2026-01-10 09:00:00 | 2026-01-10 11:39:00 | 7 | 5 |
| 1470 | daily_report | queued | 970 | 2026-02-11 10:00:00 | 2026-02-11 12:50:00 | 0 | 0 |
Expected output
| total_rows |
|---|
| 183912 |
Worked solution and explanation
What this problem really is
Strip the framing and this is a top-N-with-ties collapsed to one number: dense-rank the jobs by rows completed, keep everything down to the tenth distinct level, then sum. The tell is the tie rule. Three functions look like they answer it and only one does. ROW_NUMBER caps the set at ten rows no matter how many jobs tie. RANK honors ties but skips numbers after each one, so rnk <= 10 covers far fewer than ten distinct sizes. DENSE_RANK gives contiguous shared positions, so the surviving set grows with however many jobs tie. Every rows_done value here belongs to exactly two jobs, so a LIMIT 10 or a RANK cut stops at five sizes and reports roughly half the real total.
Break down the requirements
Step 1: Position, do not just sort
Sort alone cannot express the tie rule. You need a window function so two jobs with equal rows_done share a position and the next distinct value moves to the next integer.
Step 2: Filter on rnk
DENSE_RANK() OVER (ORDER BY rows_done DESC) then WHERE rnk <= 10 selects the ten highest distinct rows_done levels. The surviving row count is not ten; it scales with how many jobs share those values (here two per value, so twenty rows).
Step 3: Sum what survives
Sum rows_done over every row that passes the filter. One scalar out. No GROUP BY is needed since the outer query is a single aggregate, and the 32 jobs with a NULL rows_done never matter: DESC order places them after every real value, and SUM skips them anyway.
The solution
SELECT SUM(rows_done) AS total_rows
FROM (
SELECT rows_done,
DENSE_RANK() OVER (ORDER BY rows_done DESC) AS rnk
FROM batch_jobs
)
WHERE rnk <= 10COMMON FOLLOW-UP QUESTIONS
Common follow-up questions
- Restrict the ranking to jobs whose `status` is 'completed', in any casing. (Tests whether you place the filter inside the subquery so it applies before positioning, and normalize the mixed-case `status` values.)
- Return the ten highest `rows_done` values per `priority` and sum each bucket. (Probes `PARTITION BY priority` inside the window and group-level aggregation.)
- How would the answer differ if we used `RANK()` instead of `DENSE_RANK()`? (Checks understanding of position-skipping behavior and how it shrinks the surviving row set.)