The February Cohort
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
The retention team is running a re-engagement campaign targeting the February 2025 signup cohort. Pull the full profile for every user who signed up that month.
One signup window. One cohort. Who joined the club?
Tables
users
Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT
| user_id | username | signup_date | account_status | age_bucket | |
|---|---|---|---|---|---|
| 100 | alice | alice@example.com | 2025-02-02 | inactive | 25-34 |
| 197 | aaron42 | aaron42@example.com | 2026-03-03 | suspended | 35-44 |
| 294 | amelia | amelia@example.com | 2024-04-04 | pending_verification | 45-54 |
| 391 | arjun | arjun@example.com | 2025-05-05 | active | 55-64 |
| 488 | ava99 | ava99@example.com | 2026-06-06 | inactive | 65+ |
| 585 | andrew_k | andrew_k@example.com | 2024-07-07 | suspended | NULL |
| 682 | anika | anika@example.com | 2025-08-08 16:34:00 | pending_verification | 18-24 |
| 779 | aiden | aiden@example.com | 2026-09-09 14:53:00 | active | 25-34 |
| 876 | aria_b | aria_b@example.com | 2024-10-10 | inactive | 35-44 |
| 973 | brian | brian@example.com | 2025-11-11 | suspended | 45-54 |
Expected output
| user_id | username | signup_date | account_status | age_bucket | |
|---|---|---|---|---|---|
| 100 | alice | alice@example.com | 2025-02-02 | inactive | 25-34 |
| 1264 | bilal | bilal@example.com | 2025-02-14 | inactive | NULL |
| 2428 | celine | celine@example.com | 2025-02-26 | inactive | 55-64 |
| 3592 | evelyn | evelyn@example.com | 2025-02-10 | inactive | 35-44 |
| 4756 | gunnar | gunnar@example.com | 2025-02-22 | inactive | 18-24 |
Worked solution and explanation
What this is really asking
This is a one-month cohort cut dressed up as campaign targeting. The skill is anchoring year and month in the same predicate on signup_date: anyone can find February, but the trap is finding every February. signup_date spans several years, so a month-only filter like strftime('%m', signup_date) = '02' quietly adds the February 2026 signups to a 2025 list. A hand-rolled range that ends on the wrong day of February either drops time-stamped signups or is not a date at all. Either way, the campaign mails the wrong people.
Building it
Step 1: Decide what identifies the cohort
The cohort is one calendar month in one calendar year, so its key is the year-month prefix of signup_date, never the month alone. The column is ISO text, and a few rows carry a time of day after the date, so whatever you compare must ignore the time.
Step 2: Format the date down to year and month
strftime('%Y-%m', signup_date) turns every value, with or without a time part, into the same 'YYYY-MM' shape. One equality against '2025-02' then binds both components at once, so no year can leak in and no day count has to be known.
Step 3: Return the whole row, every status
"Full profile" means every column, so SELECT * is the honest projection here. Add no account_status filter and no handling for a missing age_bucket: the cohort is everyone who signed up that month.
SELECT * FROM users WHERE strftime('%Y-%m', signup_date) = '2025-02'The year-month key of signup_date pins the cohort in a single comparison.
- Month only
strftime('%m', signup_date) = '02'matches February of every year inusers. On this data it adds the February 2026 signups to the 2025 cohort: 12 rows where the answer has 9.- Year and month together
strftime('%Y-%m', signup_date) = '2025-02'matches one month in one year and nothing else, whatever time of day a signup was stamped with.
Common follow-up questions
- How would you return the size of every monthly signup cohort at once instead of one? (Tests reusing the `strftime('%Y-%m', signup_date)` key as a grouping key.)
- The table has 25 million rows and an index on `signup_date`. How do you rewrite the filter? (Tests turning the formatted predicate into a sargable half-open range.)
- What changes if `signup_date` is stored in UTC but marketing defines February in local time? (Tests shifting time zones before cutting at month boundaries.)