Still Breathing
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
- L3
- Asked in
Problem
After API credentials leaked on July 1 of 2025, every owner who held a token in api_tokens that was valid that day, going by its issue and expiry dates alone, must rotate, and the security team wants each such owner listed once, lowest owner id first. A token counts as valid if it was issued before that day and had not yet expired, and a token with no expiration date never expires.
One specific day. Which tokens were still alive?
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
| owner_id |
|---|
| 100 |
| 197 |
| 294 |
| 391 |
| 488 |
Worked solution and explanation
What this problem is really testing
This is a point-in-time validity check dressed up as incident response. Each row in api_tokens carries an issued date and, most of the time, an expires date, and the question is who held a token that was valid on one day in the past. Anyone writes the two comparisons. What separates candidates is the token with a NULL expires: it never lapses, which makes it the most dangerous credential in a leak, and a bare comparison throws it away without a word. Get the grouping wrong while rescuing it and you name owners whose tokens did not exist yet.
Build it step by step
Step 1: Keep tokens that already existed
Filter api_tokens on issued < '2025-07-01'. A token minted on or after the leak date was not around to be stolen, so the bound is strictly less-than.
Step 2: Keep tokens that had not lapsed
Add (expires IS NULL OR expires > '2025-07-01'). The NULL branch keeps never-expiring tokens; the parentheses keep both branches under the issue-date condition.
Step 3: Do not trust today's status for a past date
Leave status alone. It records whether a token is active or revoked today, and the audit is about a day more than a year ago. A token revoked last month was still a live credential on the day of the leak.
Step 4: Collapse to one row per owner
An owner can hold several valid tokens, so SELECT DISTINCT owner_id, then sort by owner_id so the rotation list reads lowest id first. Because each owner appears once, that sort is total.
SELECT DISTINCT owner_id
FROM api_tokens
WHERE issued < '2025-07-01'
AND (expires IS NULL OR expires > '2025-07-01')
ORDER BY owner_idStrict issued bound and a parenthesized NULL branch for never-expiring tokens.
SELECT DISTINCT owner_id
FROM api_tokens
WHERE issued < '2025-07-01'
AND expires IS NULL
OR expires > '2025-07-01'
ORDER BY owner_idWithout parentheses the OR splits the filter, and tokens issued after the leak slip through.
Common follow-up questions
- How does your query treat a token whose `expires` equals the leak date exactly? Was it valid that day? (Probes the inclusive versus exclusive boundary on the expiry comparison.)
- If the security team wanted the number of exposed tokens per owner, how would the query change? (Tests moving from a DISTINCT projection to a grouped aggregate.)
- Suppose revocations were logged with a timestamp. How would you fold them into the definition of a valid token? (Tests whether they see that a dated revocation history would change the validity window.)