Monthly Active Users per Endpoint

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
Maanams International

Problem

The api_calls log holds one row per request, recording the endpoint it hit, when it happened, and the user who made it. How many unique users called each endpoint during June 2026?

One endpoint, many users. Which ones showed up?

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 10 rows
endpointuser_count
/api/v1/auth/login2
/api/v1/auth/logout0
/api/v1/orders2
/api/v1/users/1
/api/v2/products3

Worked solution and explanation

This is reach versus volume dressed up as an endpoint report. Anyone can write a per-endpoint count; what separates answers is counting each person once. June 2026 contains a retry storm: one user hit '/api/v1/auth/login' four times in six minutes. Count rows and login reports 5 callers when it reached 2. Meanwhile '/api/v1/auth/logout' reports 1 when its only June call carries no user_id at all.

Walk it

Step 1: Keep only June 2026 calls

call_time is TEXT shaped like '2026-06-15 09:00:00', so strftime('%Y-%m', call_time) trims it to the month and the comparison with '2026-06' keeps June. Skip the filter and the February traffic block plus three years of backfill pour into every count.

Step 2: One row per endpoint

GROUP BY endpoint over the June rows. An endpoint only appears if it saw June traffic, which is exactly the list being asked for: ten endpoints.

Step 3: Count people, not calls

COUNT(DISTINCT user_id) collapses the retries into one person and ignores NULL ids. That is why logout lands at 0: its group exists because a call happened, but there is nobody to count.

June reach per endpoint
SELECT endpoint, COUNT(DISTINCT user_id) AS user_count FROM api_calls WHERE strftime('%Y-%m', call_time) = '2026-06' GROUP BY endpoint

One filter, one group key, one distinct count.

Counting rows
COUNT(*) gives login 5 (four storm retries plus one other caller) and logout 1 (an anonymous call). That is call volume, not reach.
Counting users
COUNT(DISTINCT user_id) gives login 2 and logout 0. Each person counts once per endpoint and anonymous calls count for no one.

Common follow-up questions