First Light

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
L6
Asked in
Samsara

Problem

We're profiling who was shipping code in each repo's scrappy early days, before it ever logged a successful CI build. For each of those authors, report their average lines added and average lines removed per commit, biggest contributions first, and alphabetically by name whenever two authors match on that.

Every repo has a scrappy stretch before its first green build. See who was shipping then, and how big their changes were.

Tables

repo_commits

Columns: commit_id INTEGER, repo_name TEXT, author TEXT, message TEXT, added INTEGER, removed INTEGER, commit_at TEXT

repo_commits: 10 of 200 rows
commit_idrepo_nameauthormessageaddedremovedcommit_at
3061backend-apibobAdd unit tests1772026-02-02 01:09:00
3122infracharlieRefactor auth module34142026-03-03 02:18:00
3183ml-pipeline charlieUpdate deps51212026-04-04 03:27:00
3244mobile-appdana Improve perf68282026-05-05 04:36:00
3305data-platformfrank Add caching layer 85352026-06-06 05:45:00
3366frontendAliceFix typo in readme102422026-07-07 06:54:00
3427backend-apiBobNULL119492026-08-08 07:03:00
3488infraaliceWIP136562026-09-09 08:12:00
3549ml-pipelinebob153632026-01-10 09:21:00
3610mobile-appcharlieAdd search endpoint170702026-02-11 10:30:00

ci_builds

Columns: build_id INTEGER, repo_name TEXT, branch TEXT, status TEXT, dur_secs INTEGER, trigger TEXT, built_at TEXT

ci_builds: 10 of 200 rows
build_idrepo_namebranchstatusdur_secstriggerbuilt_at
5047backend-apidevelopfailed34pull_request2026-02-02 01:13:00
5094infrafeature/authcanceled53schedule2026-03-03 02:26:00
5141ml-pipelinefix/login-bugrunning72manual2026-04-04 03:39:00
5188mobile-apprelease/v2.0queued91tag2026-05-05 04:52:00
5235data-platformhotfix/paymentsuccess110webhook2026-06-06 05:05:00
5282frontendfeature /spacesfailedNULLpush2026-07-07 06:18:00
5329backend-apimaincanceled148pull_request2026-08-08 07:31:00
5376infradeveloprunning167schedule2026-09-09 08:44:00
5423ml-pipelinefeature/authqueued186manual2026-01-10 09:57:00
5470mobile-appfix/login-bugsuccess205tag2026-02-11 10:10:00

Expected output

First 5 of 8 rows
authoravg_lines_addedavg_lines_removed
alice256.892.8
eve252110.18181818181819
Alice25090
charlie25090
frank244.5555555555555485.66666666666667

Worked solution and explanation

What this problem really is

Strip the costume and this is a per-repo anchored filter with one sharp edge: the anchor is not the repo's earliest build, it is the repo's first SUCCESSFUL build. So the anchor is a MIN scoped to status = 'success', joined back onto the commits, and you keep only what landed before it. Anyone can write the CTE and the join. The trick is that filtered MIN. Anchor on the earliest build of any status and you quietly change every repo's cutoff, because most repos log a failed or canceled build first, and you drop exactly the early committers this question is about.


Break down the requirements

Step 1: Anchor on each repo's first green build

Build a CTE first_success that filters ci_builds to status = 'success', groups by repo_name, and takes MIN(built_at) as first_success_at. The WHERE has to sit inside this CTE so the MIN only sees successful builds. One row per repo that ever went green; repos that never succeeded produce no row.

Step 2: Keep commits that landed before it

Join repo_commits to first_success on repo_name. The inner join is doing double duty here: it attaches the anchor AND silently discards commits to repos that never succeeded (no anchor row to match). Then keep only the early commits with commit_at < fs.first_success_at. Compare commit_at (the timestamp), never message (the commit text).

Step 3: Average per author, biggest first

Group by author and project AVG(rc.added) and AVG(rc.removed), then order by avg_lines_added descending so the biggest contributors surface first. Because the timestamps are stored as ISO text, every comparison here is a plain string comparison; no date functions are needed at all.


The solution

Filtered MIN anchor, before-window, two AVGs
WITH first_success AS (
    SELECT repo_name, MIN(built_at) AS first_success_at
    FROM ci_builds
    WHERE status = 'success'
    GROUP BY repo_name
)
SELECT
    rc.author,
    AVG(rc.added) AS avg_lines_added,
    AVG(rc.removed) AS avg_lines_removed
FROM repo_commits rc
JOIN first_success fs ON rc.repo_name = fs.repo_name
WHERE rc.commit_at < fs.first_success_at
GROUP BY rc.author
ORDER BY avg_lines_added DESC, author

Common follow-up questions