Speed and Substance

A hard SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
hard
Seniority
L5
Asked in
Kabbage

Problem

We're building an observability view over pipeline runs and want a single figure for how tightly a pipeline's speed tracks its throughput. Counting only the runs that logged both a duration and their row counts, collapse each pipeline to one point: its average run duration paired with its average net row output, where a run's net output is rows_out minus 10 percent of rows_in. There's no correlation function to lean on here, so compute the Pearson correlation between those two per-pipeline figures straight from its definition.

When a run takes longer, is it moving more rows or just stalling?

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 1 of 1 rows
correlation
0.77

Worked solution and explanation

What this problem is really testing

This is a hand-rolled Pearson correlation, and the coefficient is the easy half. The half that separates candidates is spotting that not every run is measurable: two pipelines never recorded a single duration, and plenty of runs logged a duration but no row counts, or row counts but no duration. If you average duration and net output independently without first deciding which runs count, a pipeline's x average and y average get drawn from different sets of runs, and the number you hand back answers a question nobody asked. The tell that you got it wrong: the textbook computational Pearson formula and the centered formula stop agreeing with each other, because one of them quietly correlates a sample of eight pipelines against a sample of ten.


The trap: not every run is measurable

Two pipelines in this data never logged a duration on any run, so AVG(dur_secs) for them is NULL: with no speed, they cannot be a point on a speed versus throughput plane. Many of the remaining runs are missing either a duration or a row count. Average the two figures independently and each pipeline's point is stitched from mismatched run sets; feed the duration-less pipelines into a computational Pearson and COUNT(*) reports ten while the duration sums cover only eight, so the formula divides inconsistent totals and returns garbage that can even flip sign.

Average first, filter never
AVG(dur_secs) runs over the runs that have a duration; AVG(net) runs over the runs that have row counts. Different run sets per pipeline. Two pipelines come back with a NULL duration. The computational formula counts n as ten but sums x over eight, so numerator and denominator disagree on sample size. Result: -0.19, and the centered formula lands on yet another value.
Filter to complete runs, then average
One WHERE keeps only runs with a duration and both row counts. Each pipeline's two averages share one run set, the two duration-less pipelines vanish, and n is a consistent eight everywhere. Computational and centered Pearson now agree exactly: 0.77.

Building the query

Step 1: Keep only measurable runs

A run can inform speed versus throughput only if it logged its duration and both row counts, so keep the runs where dur_secs, rows_in, and rows_out are all present. This is the line the whole problem turns on.

Step 2: Collapse each pipeline to one point

GROUP BY pipe_name and take AVG(dur_secs) as x and AVG(rows_out - 0.1 * rows_in) as y. Write 0.1 as a decimal literal so the ten percent overhead is real arithmetic and not an integer 1/10 truncated to zero.

Step 3: Broadcast the global means

Take AVG(x) and AVG(y) over the per-pipeline rows in a second CTE, then CROSS JOIN it back so every pipeline row can subtract both centroids.

Step 4: Apply Pearson by definition

Numerator is SUM((x - x_mean) * (y - y_mean)). Denominator is SQRT(SUM((x - x_mean) squared)) times SQRT(SUM((y - y_mean) squared)). Divide, round to two decimals, return the single scalar named correlation.

The solution

Manual Pearson correlation across measurable pipelines
WITH pipe_stats AS (
    SELECT pipe_name,
           AVG(dur_secs)                 AS avg_dur,
           AVG(rows_out - 0.1 * rows_in) AS avg_net_output
    FROM data_pipes
    WHERE dur_secs IS NOT NULL
      AND rows_in IS NOT NULL
      AND rows_out IS NOT NULL
    GROUP BY pipe_name
),
means AS (
    SELECT AVG(avg_dur) AS dur_mean,
           AVG(avg_net_output) AS out_mean
    FROM pipe_stats
)
SELECT ROUND(
    SUM((ps.avg_dur - m.dur_mean) * (ps.avg_net_output - m.out_mean))
    / (SQRT(SUM((ps.avg_dur - m.dur_mean) * (ps.avg_dur - m.dur_mean)))
       * SQRT(SUM((ps.avg_net_output - m.out_mean) * (ps.avg_net_output - m.out_mean)))),
    2
) AS correlation
FROM pipe_stats ps
CROSS JOIN means m

Common follow-up questions