Tokens With Non-Read Scope Prefix
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
- City and County of San Francisco
Problem
A security audit needs to verify that all API tokens have a scope starting with 'read'. Count the number of unique owners whose scope does not begin with 'read'.
Tokens that don't start with 'read'.
Tables
api_tokens
Columns: token_id INTEGER, owner_id INTEGER, scope TEXT, status TEXT, issued TEXT, expires TEXT, last_used TEXT, requests INTEGER
| token_id | owner_id | scope | status | issued | expires | last_used | requests |
|---|---|---|---|---|---|---|---|
| 1043 | 197 | write | revoked | 2025-02-02 | 2027-02-02 | 2026-02-02 | 47 |
| 1086 | 294 | admin | expired | 2025-03-03 | 2027-03-03 | 2026-03-03 | 94 |
| 1129 | 391 | read:users | Active | 2025-04-04 | 2027-04-04 | 2026-04-04 | 141 |
| 1172 | 488 | write:orders | REVOKED | 2025-05-05 | 2027-05-05 | 2026-05-05 | 188 |
| 1215 | 585 | read:analytics | active | 2025-06-06 | 2027-06-06 | 2026-06-06 | 235 |
| 1258 | 682 | full_access | revoked | 2025-07-07 | NULL | 2026-07-07 | 282 |
| 1301 | 779 | read | expired | 2025-08-08 | 2027-08-08 | 2026-08-08 | 329 |
| 1344 | 876 | write | Active | 2025-09-09 | 2027-09-09 | NULL | 0 |
| 1387 | 973 | admin | REVOKED | 2025-10-10 | 2027-10-10 | 2026-01-10 | 423 |
| 1430 | 1070 | read:users | active | 2025-11-11 | 2027-11-11 | 2026-02-11 | 470 |
Expected output
| non_read_owner_count |
|---|
| 50 |
Worked solution and explanation
Why this problem exists in real interviews
This tests string-based filtering with negation. Interviewers want to see if you can use NOT LIKE to exclude rows matching a prefix pattern.
Break down the requirements
Step 1: Identify the exclusion pattern
The audit goal is: every token must have a scope starting with 'read'. An owner VIOLATES the policy if they hold AT LEAST ONE token whose scope does not begin with 'read'.
Step 2: Return matching tokens
Group the tokens by owner_id so each owner is evaluated as a unit across all of their tokens.
The solution
SELECT COUNT(*) AS non_read_owner_count
FROM (
SELECT owner_id
FROM api_tokens
GROUP BY owner_id
HAVING SUM(CASE WHEN scope LIKE 'read%' THEN 0 ELSE 1 END) > 0
) violatorsCommon follow-up questions
- How would you list the distinct non-read scope values? (Tests adding SELECT DISTINCT scope.)
- What if scope values are case-inconsistent? (Tests LOWER(scope) NOT LIKE 'read%'.)
- How would you count tokens per non-read scope? (Tests GROUP BY scope with the NOT LIKE filter.)