Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
Subscription state is never stored — it is derived from an append-only event log of starts, renewals, failed payments, cancellations and refunds. Billing needs to know the state of every subscription as it stood on 2026-03-01, because that is the date the March invoice run used.
Return one row per subscription that existed by then, ordered by subscription_id.
Result columns · in this order
subscription_id | The subscription. |
plan | Which service it is for. |
last_event | The latest event on or before the as-of date. |
last_event_at | When that event happened. |
state | active, grace, lapsed, cancelled or refunded. |
How to approach it
Filter to the as-of date first. Everything else is picking one row per subscription and reading it.
Sample input
| event_id | subscription_id | plan | event_type | event_at |
|---|---|---|---|---|
| 1 | sub1 | music | start | 2025-11-10 |
| 2 | sub1 | music | renew | 2025-12-10 |
| 3 | sub1 | music | renew | 2026-01-10 |
| 4 | sub1 | music | renew | 2026-02-10 |
| 5 | sub2 | tv | start | 2025-12-01 |
| 6 | sub2 | tv | renew | 2026-01-01 |
| 7 | sub2 | tv | payment_failed | 2026-02-20 |
| 8 | sub3 | music | start | 2026-01-05 |
| 9 | sub3 | music | payment_failed | 2026-02-02 |
| 10 | sub4 | arcade | start | 2025-10-20 |
| 11 | sub4 | arcade | renew | 2025-11-20 |
| 12 | sub4 | arcade | cancel | 2026-02-15 |
| 13 | sub5 | tv | start | 2026-02-18 |
| 14 | sub5 | tv | refund | 2026-02-25 |
| 15 | sub6 | music | start | 2026-02-27 |
| 16 | sub6 | music | cancel | 2026-03-20 |
| 17 | sub7 | arcade | start | 2026-01-15 |
| 18 | sub7 | arcade | renew | 2026-02-15 |
| 19 | sub7 | arcade | payment_failed | 2026-02-26 |
| 20 | sub8 | tv | start | 2026-03-05 |
| 21 | sub3 | music | renew | 2026-03-08 |
| 22 | sub4 | arcade | start | 2026-03-11 |
22 rows — scroll inside the table to see them all.
Expected output
| subscription_id | plan | last_event | last_event_at | state |
|---|---|---|---|---|
| sub1 | music | renew | 2026-02-10 | active |
| sub2 | tv | payment_failed | 2026-02-20 | grace |
| sub3 | music | payment_failed | 2026-02-02 | lapsed |
| sub4 | arcade | cancel | 2026-02-15 | cancelled |
| sub5 | tv | refund | 2026-02-25 | refunded |
| sub6 | music | start | 2026-02-27 | active |
| sub7 | arcade | payment_failed | 2026-02-26 | grace |
7 rows — all rows shown.
Constraints
'2026-03-01' may influence the answer. The log runs past that date and those rows are the future as far as this question is concerned.sub8 starts on 2026-03-05.'active', cancel is 'cancelled', refund is 'refunded'.'grace' when the failure was 16 days ago or less, and 'lapsed' after that.event_id, which increases with time.subscription_id.Worked example
sub3 failed payment on 2026-02-02 and renewed on 2026-03-08. On 1 March the failure was 27 days old, so the state was 'lapsed' — the renewal had not happened yet. sub2 failed on 2026-02-20, nine days before, so it was in 'grace'.
Query the log without the date filter and sub3 reads as active, sub6 reads as cancelled, and sub8 appears with a state on a date it did not yet exist. Every one of those is a defensible answer to a question nobody asked: what is true now.
What this tests
Point-in-time reconstruction from an event log: filtering to the as-of date before picking the latest event, rather than after, and expressing a state machine whose outcome depends on how long ago the last event was.
Submit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.