Pipeline Completion Rate

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
Meta

Problem

Each run in data_pipes logs how many rows it read in and how many it wrote out, but the table mixes tiny test runs and errored runs (which record a rows_out of -1) in with real production work. Counting a run as production only when it wrote out at least 3,000 rows, report each pipeline's average input rows across its production runs.

How far do users get through the flow?

Tables

data_pipes

Columns: pipe_id INTEGER, pipe_name TEXT, status TEXT, rows_in INTEGER, rows_out INTEGER, start_at TEXT, dur_secs INTEGER

data_pipes: 10 of 200 rows
pipe_idpipe_namestatusrows_inrows_outstart_atdur_secs
131etl_usersfailed137972026-02-02 01:00:0028
162etl_eventsrunning2741942026-03-03 02:00:0051
193sync_crmqueued4112912026-04-04 03:00:0074
224agg_dailyskipped5483882026-05-05 04:00:0097
255agg_weeklySuccess6854852026-06-06 05:00:00NULL
286export_s3FAILED8225822026-07-07 06:00:00143
317import_csvsuccessNULL6792026-08-08 07:00:00166
348ml_trainfailed10967762026-09-09 08:00:00189
379dbt_buildrunning1233NULL2026-01-10 09:00:00212
410etl_ordersqueued13709702026-02-11 10:00:00NULL

Expected output

First 5 of 10 rows
pipe_nameavg_input_rows
agg_daily8494
agg_weekly10275
dbt_build9110.5
etl_events7809
etl_orders9042

Worked solution and explanation

What this problem is really about

Strip the framing and this is a grouped average with a population problem in front of it: the average is only meaningful once you decide which runs belong in it. The data_pipes log throws tiny test runs and errored runs (the ones logging rows_out of -1) into the same table as real production work. Anyone can write GROUP BY and AVG. The skill being probed is whether you scope the population first, or average everything and quietly report a number that is too low.

Why a plain average lies here

The -1 sentinel is not NULL, so AVG gives it no free pass: an errored run still carries a real rows_in, and averaging that in with the genuine production runs drags each pipeline's mean down. The small test runs do the same, and they are not even dirty data, just runs that were never meant to count. Filter neither out and every pipeline reports an average input size well below its true production figure. The fix is one predicate that removes both classes of noise at once.


Building the query

Step 1: Scope the population to production runs

WHERE rows_out >= 3000 keeps only production runs. Because -1 is far below 3,000, this same predicate discards the errored runs, and because small test runs also fall short, it discards them too: one filter, both problems solved. No status check is needed.

Step 2: Group by pipeline

GROUP BY pipe_name collapses each pipeline's surviving runs into a single row so the average is taken per pipeline.

Step 3: Average the input rows

AVG(rows_in) averages the input size across the production runs that cleared the filter, giving each pipeline its typical production batch size.

Average input rows per pipeline, over production runs only
SELECT
    pipe_name,
    AVG(rows_in) AS avg_input_rows
FROM data_pipes
WHERE rows_out >= 3000
GROUP BY pipe_name
Averages the whole log
No filter. Errored -1 runs and small test runs are folded in, so a pipeline like export_s3 reports roughly 6,900 average input rows, low enough to look plausible, which is what makes it dangerous.
Scopes first, then averages
WHERE rows_out >= 3000 keeps only production runs, and export_s3 reports its true ~11,097. The answers diverge on every pipeline, because every pipeline has noise runs pulling its unfiltered mean down.

Common follow-up questions