Welcome Wagon
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
- City and County of San Francisco
Problem
For the growth team's annual review, how many accounts in the users table signed up during calendar year 2025?
How many signed up this year?
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
| signup_count |
|---|
| 59 |
Worked solution and explanation
What this warm-up is really checking
This is a two-sided date window dressed up as a headcount. Anyone can write COUNT(*). What separates candidates is whether the year is fenced on both ends. Last year sits in the middle of the data: there are signups before it and signups after it in 2026. Write only signup_date >= '2025-01-01' and every signup from this year joins last year's total, so the annual review reports growth that never happened.
Step 1: Open the window on January 1
signup_date >= '2025-01-01' drops every signup from 2023 and 2024. On its own it is not a year filter. It means 'since last year began', and that includes today.
Step 2: Close it on the next January 1, exclusive
signup_date < '2026-01-01' cuts off this year's signups. Use a strict less-than against the first day of the next year, not <= '2025-12-31'. Some signup_date values already carry a time of day, and a signup at 18:00 on December 31 sorts after the bare date string, so the inclusive form would lose it.
Step 3: Count what survives
COUNT(*) over the filtered rows is the answer. A timestamped value such as '2025-08-08 16:34:00' still sorts between the two text bounds, so it lands in its year with no conversion and no special case.
SELECT COUNT(*) AS signup_count
FROM users
WHERE signup_date >= '2025-01-01'
AND signup_date < '2026-01-01'- One-sided filter
WHERE signup_date >= '2025-01-01'reads like 'last year' but counts last year plus everything in 2026 so far.- Two-sided filter
signup_date >= '2025-01-01' AND signup_date < '2026-01-01'counts exactly one calendar year, no matter how much data sits on either side.
Common follow-up questions
- How would you show last year's signups per month? (Keep the same two-sided window and add a month bucket of `signup_date` as the grouping key.)
- How would you compute year-over-year signup growth? (Count two adjacent windows, using either conditional aggregates or one row per year compared with the previous row.)
- What changes if `signup_date` is stored as a timestamp in UTC but the review is in local time? (Shift the bounds, not the column, so the range stays index-friendly.)