Health Checks per Service

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
Apple

Problem

Services with the same number of recorded health checks are listed alphabetically by name. Count every check svc_health holds for each service and list the services most-monitored first.

Some services get checked constantly.

Tables

svc_health

Columns: check_id INTEGER, svc_name TEXT, status TEXT, latency REAL, uptime REAL, checked TEXT, region TEXT

svc_health: 10 of 200 rows
check_idsvc_namestatuslatencyuptimecheckedregion
137payment-apidegraded3.697.032026-02-02 01:05:00us-west-2
174user-svcunhealthy6.794.062026-03-03 02:10:00eu-west-1
211search-apitimeout9.891.092026-04-04 03:15:00ap-south-1
248gatewayHealthy12.998.122026-05-05 04:20:00eu-central-1
285notif-svcDEGRADED1695.152026-06-06 05:25:00us-east-1
322ml-servinghealthy19.192.182026-07-07 06:30:00us-west-2
359cache-svcdegradedNULL99.212026-08-08 07:35:00eu-west-1
396queue-workerunhealthy25.396.242026-09-09 08:40:00ap-south-1
433cron-svctimeout28.493.272026-01-10 09:45:00eu-central-1
470auth-svcHealthy31.590.32026-02-11 10:50:00us-east-1

Expected output

First 5 of 15 rows
svc_namecheck_count
auth-svc18
cache-svc18
cron-svc18
edge-auth-svc4
event-bus4

Worked solution and explanation

This is a row tally with a sort that has to be total, dressed up as a monitoring-coverage audit. Anyone writes the grouping. What separates candidates is noticing two things about this data. Every row is one check, so the tally is COUNT(*), not a count of some column that happens to be filled: 23 checks have no latency, and COUNT(latency) quietly drops them. And the counts barely spread: ten services sit at 18 checks and five at 4, so a sort on the count alone leaves every row in a tie and the name decides the entire sequence.

Walk it

Step 1: Decide what one row is

Each svc_health row is one recorded check. The status column is messy ('Healthy' beside 'healthy', 'DEGRADED' beside 'degraded'), which tempts people to clean or filter it first. Coverage counts every check whatever it reported, so status never enters the query.

Step 2: Tally rows, not values

COUNT(*) counts rows; COUNT(latency) counts rows where latency is filled. The checks whose timing never landed are still checks, so the row count is the coverage number, aliased check_count.

Step 3: Make the order total

Sort by check_count DESC, then svc_name. With two distinct counts across fifteen services, the second key is doing almost all the ordering work, and it is the one people leave off.

Checks per service, most-monitored first
SELECT svc_name, COUNT(*) AS check_count
FROM svc_health
GROUP BY svc_name
ORDER BY check_count DESC, svc_name

One row per svc_name; the name settles every tie inside the 18 and 4 blocks.

Count alone
ORDER BY check_count DESC puts the 18s before the 4s and stops there. Inside each block the rows arrive in whatever order the hash aggregate emitted them, which can differ between runs and between engines.
Count, then name
ORDER BY check_count DESC, svc_name fixes every position: 'auth-svc', 'cache-svc', 'cron-svc' lead the 18s, and 'edge-auth-svc' and 'event-bus' lead the 4s.

Common follow-up questions