Nobody Was Watching
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
- Fidelity
Problem
Which services deployed with no corresponding alert record? Pull every deployment that has no matching alert for its service. Show the service name, version, environment, and deployment status, with the most recent deployment first.
Every release shipped clean. Not one had a tripwire set. Find the ones flying blind.
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
| log_id | svc_name | version | env_name | status | deploy_at | dur_secs | author |
|---|---|---|---|---|---|---|---|
| 131 | payment-api | v1.0.2 | staging | failed | 2026-02-02 01:11:00 | 23 | bob |
| 162 | user-svc | v1.1.0 | dev | rolled_back | 2026-03-03 02:22:00 | 36 | charlie |
| 193 | search-api | 2.0.0 | canary | in_progress | 2026-04-04 03:33:00 | 49 | dana |
| 224 | gateway | v2.1.0 | Production | Success | 2026-05-05 04:44:00 | 62 | eve |
| 255 | notif-svc | 2.1.1 | STAGING | FAILED | 2026-06-06 05:55:00 | 75 | frank |
| 286 | analytics | v3.0.0-rc1 | production | success | 2026-07-07 06:06:00 | 88 | Alice |
| 317 | ml-serving | v1.0.3 | staging | failed | 2026-08-08 07:17:00 | NULL | BOB |
| 348 | auth-svc | v1.0.1 | dev | Rolled_Back | 2026-09-09 08:28:00 | 114 | alice |
| 379 | Payment-API | v1.0.2 | canary | in_progress | 2026-01-10 09:39:00 | 127 | bob |
| 410 | user-svc | v1.1.0 | Production | Success | 2026-02-11 10:50:00 | 140 | charlie |
alert_events
Columns: alert_id INTEGER, svc_name TEXT, severity TEXT, status TEXT, fired_at TEXT, ack_by TEXT, resolved TEXT
| alert_id | svc_name | severity | status | fired_at | ack_by | resolved |
|---|---|---|---|---|---|---|
| 129 | payment-api | high | acknowledged | 2026-02-02 01:07:00 | bob | 2026-02-02 03:11:00 |
| 158 | user-svc | medium | resolved | 2026-03-03 02:14:00 | charlie | 2026-03-03 04:22:00 |
| 187 | search-api | low | silenced | 2026-04-04 03:21:00 | dana | NULL |
| 216 | gateway | Critical | firing | 2026-05-05 04:28:00 | NULL | 2026-05-05 06:44:00 |
| 245 | notif-svc | HIGH | acknowledged | 2026-06-06 05:35:00 | alice | 2026-06-06 07:55:00 |
| 274 | db-primary | critical | resolved | 2026-07-07 06:42:00 | bob | NULL |
| 303 | cache-01 | high | silenced | 2026-08-08 07:49:00 | charlie | 2026-08-08 09:17:00 |
| 332 | auth-svc | medium | firing | 2026-09-09 08:56:00 | NULL | 2026-09-09 10:28:00 |
| 361 | payment-api | low | acknowledged | 2026-01-10 09:03:00 | eve | NULL |
| 390 | user-svc | Critical | resolved | 2026-02-11 10:10:00 | alice | 2026-02-11 12:50:00 |
Expected output
| svc_name | version | env_name | status |
|---|---|---|---|
| analytics | v3.0.0-rc1 | dev | rolled_back |
| payment-api | v1.0.2 | STAGING | FAILED |
| ml-serving | v1.0.3 | STAGING | FAILED |
| payment-api | v1.0.2 | canary | in_progress |
| Payment-API | v1.0.2 | canary | in_progress |
Worked solution and explanation
What this problem really is
This is a set difference wearing an incident-review costume: which deployments belong to a service that never shows up in the alert table at all. Everyone reaches for a membership check, and that is exactly where it bites. Write NOT IN against a list of alert service names and the moment one alert row carries a NULL service, the whole result quietly collapses to zero rows. Flip to an INNER JOIN and you get the mirror image: deployments that DID alert. Only the LEFT JOIN with alert_id IS NULL survives, and you need both halves. Drop either one and you ship the wrong answer with a straight face.
Break down the requirements
Step 1: Left join on the service
LEFT JOIN deploy_logs to alert_events on svc_name alone. Match on the service, not the version or environment: one alert anywhere for a service knocks out all of its deployments. Unmatched deployments carry NULL alert columns.
Step 2: Filter for no match
WHERE ae.alert_id IS NULL keeps only the rows that found no partner. Filter on a NEVER-NULL alert column like the primary key; a nullable column would let real alerts leak through as false negatives.
Step 3: Sort by recency
ORDER BY deploy_at DESC puts the freshest deployments on top, which is what on-call scans first. Note repeats of the same service each stand as their own row; nothing here deduplicates.
The solution
SELECT dl.svc_name, dl.version, dl.env_name, dl.status
FROM deploy_logs dl
LEFT JOIN alert_events ae ON dl.svc_name = ae.svc_name
WHERE ae.alert_id IS NULL
ORDER BY dl.deploy_at DESCCommon follow-up questions
- What is the performance difference between LEFT JOIN + IS NULL and NOT EXISTS? (NOT EXISTS can short-circuit on the first match; LEFT JOIN must complete the full join. Tests optimizer awareness.)
- What if the join should also match on time window (alert within 1 hour of deploy)? (Add a time condition to the join, making the anti-join more specific.)
- How would you count the number of alert-free deployments per service? (Wrap in a GROUP BY `svc_name` with COUNT(*).)