Loudest in the Room

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

Problem

Our daily busiest-endpoints panel no longer matches what on-call sees in api_calls, partly because some endpoint paths were logged with stray spaces around them and show up as two different endpoints. For every day, return the endpoints whose call count is among that day's three highest counts, with the day, the cleaned endpoint, and its level (1 for the busiest count, 3 for the third highest).

Every day, a few endpoints carry the load. Surface them.

Tables

api_calls

Columns: call_id INTEGER, endpoint TEXT, method TEXT, status INTEGER, latency REAL, user_id INTEGER, call_time TEXT, err_msg TEXT

api_calls: 10 of 670 rows
call_idendpointmethodstatuslatencyuser_idcall_timeerr_msg
8079/api/v1/ordersPOST2004.21002026-02-02 01:07:00NULL
8158/api/v2/productsPUT2007.91972026-03-03 02:14:00NULL
8237/api/v1/searchDELETE20111.62942026-04-04 03:21:00NULL
8316/api/v1/auth/loginPATCH20415.33912026-05-05 04:28:00NULL
8395/api/v1/auth/logoutget30119NULL2026-06-06 05:35:00NULL
8474/api/v2/analyticspost40022.75852026-07-07 06:42:00Not found
8553/api/v1/paymentsGET40126.46822026-08-08 07:49:00Unauthorized
8632/api/v1/users/POST40330.17792026-09-09 08:56:00Rate limit exceeded
8711/api/v2/products/PUT40433.88762026-01-10 09:03:00Internal server error
8790/api/v1/usersDELETE50037.5NULL2026-02-11 10:10:00Bad gateway

Expected output

First 5 of 336 rows
call_dayendpointrnk
2023-01-01/api/v1/users1
2023-01-12/api/v1/auth/logout1
2026-02-01/api/v1/search2
2026-02-01/api/v1/auth/login3
2026-02-02/api/v1/users2

Worked solution and explanation

What this really is

Strip the ops-dashboard costume and this is top-N-per-group, with the twist that trips people: N counts count-levels, not rows. You clean the endpoint path, count calls per day and endpoint, order the endpoints within a day by that count, and keep the three highest counts. Two decisions settle whether you pass: which ranking function you reach for, and where you put the level filter. Miss either and the query still runs, it just hands back the wrong set.


The traps


The build

Step 1: Count calls per day and cleaned endpoint

In daily_counts, bucket call_time to its calendar date with DATE(call_time), strip the path with TRIM(endpoint), and COUNT(*) grouped by both. Grouping on the raw timestamp would split each day into per-second fragments; grouping on the raw path would split padded endpoints in two.

Step 2: Assign a level within each day

In ranked, apply DENSE_RANK() OVER (PARTITION BY call_day ORDER BY call_count DESC). Partitioning by day restarts the numbering every day, descending count puts the busiest endpoint at level 1, and DENSE_RANK makes equal counts share a level with no gaps, so level 3 is the third-highest count.

Step 3: Filter to the three highest counts outside the window

In the outer query keep rows where rnk <= 3 and return the day, the endpoint and the level. Because equal counts share a level, a day can legitimately return more than three rows, and that is intended: it is exactly what a row cap would hide.

The solution

Clean, count per day-endpoint, level per day, filter outside
WITH daily_counts AS (
  SELECT DATE(call_time) AS call_day,
         TRIM(endpoint) AS endpoint,
         COUNT(*) AS call_count
  FROM api_calls
  GROUP BY DATE(call_time), TRIM(endpoint)
),
ranked AS (
  SELECT call_day,
         endpoint,
         DENSE_RANK() OVER (PARTITION BY call_day ORDER BY call_count DESC) AS rnk
  FROM daily_counts
)
SELECT call_day, endpoint, rnk
FROM ranked
WHERE rnk <= 3

Common follow-up questions