Shipped to Prod

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
L3
Asked in
Shopify

Problem

The release manager wants to see how deployment volume splits across the pipeline. Count how many deployments landed in each environment, busiest environment first.

Every environment keeps its own tally. Read the funnel.

Tables

deploy_logs

Columns: log_id INTEGER, svc_name TEXT, version TEXT, env_name TEXT, status TEXT, deploy_at TEXT, dur_secs INTEGER, author TEXT

deploy_logs: 10 of 200 rows
log_idsvc_nameversionenv_namestatusdeploy_atdur_secsauthor
131payment-apiv1.0.2stagingfailed2026-02-02 01:11:0023bob
162user-svcv1.1.0devrolled_back2026-03-03 02:22:0036charlie
193search-api2.0.0canaryin_progress2026-04-04 03:33:0049dana
224gatewayv2.1.0ProductionSuccess2026-05-05 04:44:0062eve
255notif-svc2.1.1STAGINGFAILED2026-06-06 05:55:0075frank
286analyticsv3.0.0-rc1productionsuccess2026-07-07 06:06:0088Alice
317ml-servingv1.0.3stagingfailed2026-08-08 07:17:00NULLBOB
348auth-svcv1.0.1devRolled_Back2026-09-09 08:28:00114alice
379Payment-APIv1.0.2canaryin_progress2026-01-10 09:39:00127bob
410user-svcv1.1.0ProductionSuccess2026-02-11 10:50:00140charlie

Expected output

First 5 of 7 rows
env_namedeploy_count
staging34
canary34
dev33
production32
Dev1

Worked solution and explanation

Strip the deployment-pipeline costume and this is a plain bucket-and-tally: one row per environment, with a headcount of deploys in each. Everyone gets the grouping. The thing that quietly separates people is which count they reach for and how they order the result. Pick the wrong count and you silently drop rows; forget the ordering and the release manager cannot read the funnel at a glance.

The trap: which COUNT do you write?

The instinct on a table like this is to count some column that feels representative, say COUNT(dur_secs). That is a trap. dur_secs is nullable (the ml-serving staging row has no duration), and COUNT(column) skips NULLs. Count that column and staging comes back short instead of matching its true deploy count. The question asks for deployment volume, meaning every logged row, so you want COUNT(*), which counts rows and never inspects a value.

Deploys per environment, busiest first
SELECT env_name, COUNT(*) AS deploy_count
FROM deploy_logs
GROUP BY env_name
ORDER BY deploy_count DESC

GROUP BY collapses to one row per environment; COUNT(*) tallies every deploy; ORDER BY deploy_count DESC puts the busiest environment on top.

Step 1: Collapse to one row per environment

GROUP BY env_name defines the grain of the answer. env_name has only four distinct values here, so you get exactly four output rows regardless of how many hundreds of thousands of deploy logs feed in.

Step 2: Tally every row in each bucket

COUNT(*) counts rows within each group. Because it never looks at a column value, in_progress, failed, and rolled_back deploys all count the same as a success, which is exactly what 'total deployment volume' means.

Step 3: Order so the funnel reads top-down

ORDER BY deploy_count DESC surfaces the busiest environment first. That is the whole point of the report: the release manager wants to see where volume concentrates without scanning the whole table.

COUNT(*)
Counts every row in the group. Answers 'how many deployments'.
COUNT(`dur_secs`)
Counts only rows where dur_secs is present, so any NULL-duration deploy is dropped. Answers a subtly different question and is wrong here.

Common follow-up questions