Peak Hour Power Callers

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

Problem

Afternoon API traffic between 3 and 6 PM keeps spiking, and the on-call support engineer wants to know which callers in api_calls are driving it. List each user with at least 3 calls in that window and their call count, busiest first, with calls that carry no user id counted together as a single caller.

One hour. The phone lines exploded.

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 4 of 4 rows
user_idcall_count
3914
37863
15553
NULL3

Worked solution and explanation

What this really is

Strip the costume and this is a per-caller frequency count fenced inside a recurring time-of-day window. The window is what bites first: call_time is a full timestamp spread over years of days, so any plain range on it selects one stretch of the calendar, not the same 3 to 6 PM slice on every day. Only the hour read out of each row isolates the afternoon. After that, the skill is keeping two filters apart: the window filters calls, and the 'at least 3' test filters callers. Read '3 to 6 PM' as hours 15 through 18 and you fold the whole 6 PM hour into every count.


The two-stage filter

Step 1: Fence the afternoon window

The window is a time of day, not a date range, so pull the hour out of call_time and keep 15, 16 and 17. EXTRACT(HOUR FROM call_time) BETWEEN 15 AND 17 captures 15:00:00 through 17:59:59 on every day in the table. Comparing call_time itself against '15:00:00' and '18:00:00' looks right and matches nothing, because every value starts with a date.

Step 2: Count per caller, keep the heavy hitters

Collapse the surviving rows to one row per caller with GROUP BY user_id, then keep the heavy hitters with HAVING COUNT(*) >= 3. Calls with no user_id fall into one group of their own, which the statement keeps as a single caller. COUNT(*) counts that group's rows; COUNT(user_id) would score it 0 and quietly drop it.

Step 3: Sort busiest first

Return the caller and the count with ORDER BY call_count DESC. Callers tied on a count can come back in any order: the question asks who is busiest, and nothing in it ranks two equally busy callers.


The solution

Hour-of-day window, per-caller threshold, busiest first
SELECT user_id, COUNT(*) AS call_count
FROM api_calls
WHERE EXTRACT(HOUR FROM call_time) BETWEEN 15 AND 17
GROUP BY user_id
HAVING COUNT(*) >= 3
ORDER BY call_count DESC

Common follow-up questions