The Compliance Order

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
Amazon

Problem

List every token in api_tokens with its scope, alphabetically by the second character of the scope, as the line-up for a compliance audit trail. Tokens sharing that character run from earliest issued to latest, and tokens still tied on issue date go lowest token id first.

Token scopes need to be in the right sequence before the audit.

Tables

api_tokens

Columns: token_id INTEGER, owner_id INTEGER, scope TEXT, status TEXT, issued TEXT, expires TEXT, last_used TEXT, requests INTEGER

api_tokens: 10 of 200 rows
token_idowner_idscopestatusissuedexpireslast_usedrequests
1043197writerevoked2025-02-022027-02-022026-02-0247
1086294adminexpired2025-03-032027-03-032026-03-0394
1129391read:usersActive2025-04-042027-04-042026-04-04141
1172488write:ordersREVOKED2025-05-052027-05-052026-05-05188
1215585read:analyticsactive2025-06-062027-06-062026-06-06235
1258682full_accessrevoked2025-07-07NULL2026-07-07282
1301779readexpired2025-08-082027-08-082026-08-08329
1344876writeActive2025-09-092027-09-09NULL0
1387973adminREVOKED2025-10-102027-10-102026-01-10423
14301070read:usersactive2025-11-112027-11-112026-02-11470

Expected output

First 5 of 200 rows
token_idscope
10005386admin
10005351admin
10005361read:analytics
10005366read:users
10005391read

Worked solution and explanation

What this is really testing

This looks like a plain sort, but the sort key is not a column. 'Alphabetically by the second character of its scope' means you order by an expression: the single character at position 2, pulled out with SUBSTR(scope, 2, 1). The tell for a weaker answer is ORDER BY scope, which collates the whole string from its first character. On this seed that changes the result in two places: 'full_access' (second character 'u') belongs at the very end, after every 'write' scope, but a whole-string sort puts it right after 'admin'. And inside the 'e' group, 'read', 'read:analytics' and 'read:users' should interleave by issue date instead of sitting in three separate blocks.


Build the ordering

Step 1: Order by the extracted second character

The primary key is the character at position 2. SUBSTR(scope, 2, 1) takes exactly one character starting at index 2, so 'admin' yields 'd' and every 'read' variant yields 'e'. Sort on that expression, not on scope.

Step 2: Break ties by issue date, then token id

When two scopes share that second character, the earliest-issued token comes first, so issued is the next sort key. It is not enough on its own: on this seed, 16 pairs of tokens share both the scope and the issue date. The statement names token_id (which is unique) as the last key. Without it, those pairs come back in whatever order the engine likes and fail an order-sensitive check.

Step 3: Select exactly the two columns asked for

Return only token_id and scope. No status filter: the audit covers every token, and the mixed-case status values are a distractor.


The solution

Order by the second scope character, then issue date
SELECT token_id, scope
FROM api_tokens
ORDER BY SUBSTR(scope, 2, 1) ASC, issued, token_id

Common follow-up questions