Open Wounds

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
L4
Asked in
Google

Problem

During an incident review, the on-call team needs the oldest unresolved alert for each service. Walk the services in alphabetical order, showing each one's name, the alert ID, the severity, the status, and the time the alert was fired.

Every service has one alarm that was never silenced. Find the one that has been screaming the longest.

Tables

alert_events

Columns: alert_id INTEGER, svc_name TEXT, severity TEXT, status TEXT, fired_at TEXT, ack_by TEXT, resolved TEXT

alert_events: 10 of 200 rows
alert_idsvc_nameseveritystatusfired_atack_byresolved
129payment-apihighacknowledged2026-02-02 01:07:00bob2026-02-02 03:11:00
158user-svcmediumresolved2026-03-03 02:14:00charlie2026-03-03 04:22:00
187search-apilowsilenced2026-04-04 03:21:00danaNULL
216gatewayCriticalfiring2026-05-05 04:28:00NULL2026-05-05 06:44:00
245notif-svcHIGHacknowledged2026-06-06 05:35:00alice2026-06-06 07:55:00
274db-primarycriticalresolved2026-07-07 06:42:00bobNULL
303cache-01highsilenced2026-08-08 07:49:00charlie2026-08-08 09:17:00
332auth-svcmediumfiring2026-09-09 08:56:00NULL2026-09-09 10:28:00
361payment-apilowacknowledged2026-01-10 09:03:00eveNULL
390user-svcCriticalresolved2026-02-11 10:10:00alice2026-02-11 12:50:00

Expected output

First 5 of 8 rows
svc_namealert_idseveritystatusfired_at
auth-svc10003096criticalfiring2022-12-13 00:12:00
cache-0110003087lowsilenced2023-03-04 15:09:00
db-primary10003006criticalresolved2022-06-07 06:42:00
gateway10003036criticalfiring2022-12-09 12:12:00
notif-svc10003021lowacknowledged2022-09-22 21:27:00

Worked solution and explanation

What this really is

This is a per-group earliest-row pick wearing an incident-management costume, and the row has to come back whole: id, severity and status of the winning alert, not just its time. Everyone lands the window function. What separates candidates is the single word 'unresolved'. Two columns describe closure and they disagree: an operator can flip status to 'resolved' while the resolved timestamp was never written, and leave status at 'firing' on an alert closed hours ago. Trust the label and you drop alerts that are still bleeding and crown closed ones as the oldest open. The timestamp is the authority: open means resolved IS NULL.


Reading the requirements

Step 1: Filter to genuinely open alerts

WHERE resolved IS NULL keeps only alerts nobody ever closed. It never touches status, because the label and the timestamp contradict each other in this data.

Step 2: Number oldest-first within each service

ROW_NUMBER() OVER (PARTITION BY svc_name ORDER BY fired_at ASC) numbers each service's open alerts from oldest to newest, so the earliest fired alert per service gets 1. ROW_NUMBER (not RANK) hands out exactly one 1 per service even if two alerts fired at the same instant.

Step 3: Keep the winner per service

Wrap it in ranked_open_alerts and keep WHERE rn = 1. The whole row (id, severity, status) rides along with the winning fired_at, which a per-service MIN(fired_at) cannot give you without a second trip back to the table.

Step 4: Order the output by service

ORDER BY svc_name gives the reviewer the alphabetical read of the board the statement asks for.


The solution

Single-pass per-service oldest open alert
SELECT svc_name, alert_id, severity, status, fired_at
FROM (
    SELECT
        svc_name, alert_id, severity, status, fired_at,
        ROW_NUMBER() OVER (PARTITION BY svc_name ORDER BY fired_at ASC) AS rn
    FROM alert_events
    WHERE resolved IS NULL
) AS ranked_open_alerts
WHERE rn = 1
ORDER BY svc_name
status <> 'resolved'
Reads the label. db-primary's alert 274 says 'resolved' with a null resolved timestamp, so it is still open, and this filter throws it away. On the seed db-primary's true oldest open alert, 10003006, is labelled 'resolved' too, so the service gets the wrong winner, while gateway's alert 216 reads 'firing' despite being closed and gets let in.
resolved IS NULL
Reads the authority. It keeps exactly the alerts no one ever closed, whatever the status text claims, and admits none that were closed. Status is still shown in the output, just never used to decide.

Common follow-up questions