Keys That Never Die

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
Amazon

Problem

An auditor going through api_tokens noticed that some tokens have no expires date at all, so they never lapse no matter what their status says. What percentage of all tokens are these never-expiring ones, returned as a decimal percentage named perpetual_pct?

Some API keys have no expiry date at all. That should worry someone.

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 1 of 1 rows
perpetual_pct
16

Worked solution and explanation

What this really is

This is a NULL-rate dressed up as a security audit. Everyone sees that the risky tokens are the ones with no expires. What separates candidates is two quiet details: counting the NULL rows rather than the filled ones, and dividing so the share survives as a decimal. Miss the first and you report 84, the safe tokens. Miss the second and 32 over 200 truncates to 0, and the audit says there is no risk at all.

Step 1: Flag the tokens with no expiry

A token lives forever when expires IS NULL. Writing expires = NULL compares against unknown and never matches. Wrap the test as CASE WHEN expires IS NULL THEN 1 ELSE 0 END so every row contributes a 1 or a 0, and SUM of that is the perpetual count.

Step 2: Take the whole population as the denominator

COUNT(*) counts every token, revoked and expired ones included. Status is mixed-case noise here and plays no part: the risk is the missing date, not the label.

Step 3: Make the share a decimal before scaling

SUM(...) and COUNT(*) are both integers, and integer over integer floors to 0 when the top is smaller. CAST(... AS REAL) turns the numerator into a decimal first, so 32 over 200 stays 0.16, and multiplying by 100 gives the percentage.

One scan, one flag, one decimal division
SELECT CAST(SUM(CASE WHEN expires IS NULL THEN 1 ELSE 0 END) AS REAL) / COUNT(*) * 100 AS perpetual_pct FROM api_tokens
Integer division
SUM(CASE ...) / COUNT(*) * 100 computes 32 / 200 = 0 first, then 0 * 100 = 0. The audit comes back clean.
Decimal division
CAST(SUM(CASE ...) AS REAL) / COUNT(*) * 100 computes 0.16, then 16.0. The order of operations is exactly why the cast has to sit on the numerator.

Common follow-up questions