Average Response Time by Hour
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
- Lyft
Problem
Users in Asia-Pacific keep reporting slow page loads during their morning. To check whether the servers show a time-of-day pattern, compute the average response time for each hour of the day and present the hours in chronological order.
Hour by hour. When does latency spike?
Tables
server_logs
Columns: log_id INTEGER, server_name TEXT, log_level TEXT, message TEXT, response_time_ms INTEGER, log_timestamp TEXT
| log_id | server_name | log_level | message | response_time_ms | log_timestamp |
|---|---|---|---|---|---|
| 137 | web-prod-02 | WARN | Connection timeout after 30s | 23 | 2026-02-02 01:07:13 |
| 174 | api-prod-01 | ERROR | Database query slow: 2.5s | NULL | 2026-03-03 02:14:26 |
| 211 | api-prod-02 | DEBUG | Cache miss for key user_123 | 49 | 2026-04-04 03:21:39 |
| 248 | db-primary | CRITICAL | Memory usage at 85% | 0 | 2026-05-05 04:28:52 |
| 285 | db-replica-01 | INFO | SSL certificate expires in 7 days | NULL | 2026-06-06 05:35:05 |
| 322 | cache-01 | WARN | Rate limit exceeded for IP 192.168.1.x | 88 | 2026-07-07 06:42:18 |
| 359 | worker-01 | ERROR | Disk space low: 10% remaining | 101 | 2026-08-08 07:49:31 |
| 396 | cdn-edge-us | DEBUG | New deployment v2.3.1 started | NULL | 2026-09-09 08:56:44 |
| 433 | cdn-edge-eu | CRITICAL | Health check passed | 127 | 2026-01-10 09:03:57 |
| 470 | monitor-01 | INFO | Failed to connect to upstream | 140 | 2026-02-11 10:10:10 |
Expected output
| hour_of_day | avg_response_time |
|---|---|
| 0 | 790 |
| 1 | 647 |
| 2 | NULL |
| 3 | 673 |
| 4 | 679.8 |
Worked solution and explanation
What this is really asking
This is a time-of-day profile dressed up as an Asia-Pacific latency complaint. Every row of server_logs records a moment, but the question wants a recurring bucket: the hour on the clock, so months of logs fold into 24 rows. Anyone can write AVG(response_time_ms). The trap is grouping on log_timestamp itself or on its date. Nearly every timestamp is its own group, and a date bucket gives one row per day, so the morning pattern never shows up.
The second trap is quieter. strftime('%H', log_timestamp) hands back text like '07', and the expected answer is the number 7. The hours where no row recorded a response time still belong in the profile, with a blank average.
Break down the requirements
Step 1: Derive the hour from log_timestamp
Pull the hour-of-day field out of the full datetime and cast it to an integer, so the bucket reads 0 to 23 rather than '00' to '23'. This derived value is the grouping key; the stored column never can be.
Step 2: Average response_time_ms per hour
AVG already skips NULLs, so a missing reading neither drags the mean toward zero nor counts as a row. An hour whose readings are all missing comes back NULL, and that is the right answer.
Step 3: Sort by hour_of_day
Ascending on the integer key reads as a daily timeline. On text keys the sort happens to work only because of the zero padding, and the column would still be the wrong type.
The solution
SELECT CAST(strftime('%H', log_timestamp) AS INTEGER) AS hour_of_day,
AVG(response_time_ms) AS avg_response_time
FROM server_logs
GROUP BY hour_of_day
ORDER BY hour_of_day ASC;Common follow-up questions
Common follow-up questions
- How would you report these hours in Asia-Pacific local time? (Shift before extracting, for example `log_timestamp + INTERVAL '8 hours'`, or better, store timestamps with an explicit zone.)
- What if the slow loads live in the p95, not the mean? (Swap or pair the average with a per-hour percentile such as `PERCENTILE_CONT(0.95)`.)
- Can you add a `server_name` breakdown without flooding the result? (Group by hour and `server_name`, then keep the worst few servers per hour with `ROW_NUMBER()`.)