Where The Rows Go

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
L5

Problem

The data platform team measures how efficiently each pipeline run turns the rows it reads into the rows it writes back out. For every run, show the pipeline name, its start time, and the ratio of rows written to rows read to four decimal places, ordered by pipeline name and then start time. Some runs never captured an output count and store -1 in its place; those runs have no meaningful ratio, so leave it empty.

Every run loses a little on the way. Measure what makes it through.

Tables

data_pipes

Columns: pipe_id INTEGER, pipe_name TEXT, rows_in INTEGER, rows_out INTEGER, start_at TEXT, status 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 200 rows
pipe_namestart_atthroughput_ratio
agg_daily2025-02-15 14:00:00NULL
agg_weekly2026-01-18 21:00:00NULL
dbt_build2025-01-22 01:00:00NULL
etl_events2023-02-03 02:00:000.708
etl_orders2026-01-07 18:00:00NULL

Worked solution and explanation

A sentinel hiding in the numerator

Beneath the throughput-metric costume this is two small correctness traps stacked on a trivial SELECT. First, rows_out / rows_in is integer division in SQL: 97/137 comes back as 0, not 0.708, so every sub-1 ratio silently collapses to zero. Second, a run that never recorded its output stores -1 in rows_out, and left alone that -1 divides into a small negative ratio that looks like real data. Anyone can write the SELECT and the ORDER BY; what separates candidates is forcing float division with * 1.0 and blanking the -1 placeholder with NULLIF so the uncomputable runs read empty instead of wrong. Miss either and the query still runs, which is exactly why it is dangerous.


Build it in three moves

Step 1: Force real division

Multiply rows_out by 1.0 before dividing so the engine switches to floating-point. rows_out * 1.0 / rows_in gives 0.7080; rows_out / rows_in gives 0. This single * 1.0 is what keeps every sub-1 ratio from collapsing to zero.

Step 2: Neutralize the placeholder

A run that never captured an output count stores -1 in rows_out. Treated as a real number it produces a negative ratio, so wrap the numerator in NULLIF(rows_out, -1): the -1 becomes NULL, the division yields NULL, and the run stays in the output with a blank ratio. Genuinely missing (NULL) read or write counts propagate to a blank ratio on their own.

Step 3: Project and order

Project pipe_name, start_at, and the rounded ratio, then order by pipe_name, start_at so runs of the same pipeline read chronologically.


The solution

Per-run throughput ratio
SELECT
    pipe_name,
    start_at,
    ROUND(NULLIF(rows_out, -1) * 1.0 / rows_in, 4) AS throughput_ratio
FROM data_pipes
ORDER BY pipe_name, start_at
Placeholder left in (wrong)
ROUND(rows_out / rows_in, 4) Integer division makes 97/137 = 0, so every ratio under 1 becomes 0.0000, and the -1 rows compute -1 divided by rows_in, a tiny negative ratio. The query returns rows and looks fine.
Guarded (correct)
ROUND(NULLIF(rows_out, -1) * 1.0 / rows_in, 4) 97 * 1.0 / 137 = 0.708029..., rounded to 0.7080, and a -1 output becomes NULL, so unrecorded runs read as empty instead of impossible.

Common follow-up questions