codejump
HardSQL

Measure Mature Day-Seven Retention

SQLDatabasesCohort Analysis

A cohort is all users sharing signup_day. Measure activity on exactly signup_day + 7 calendar days, not anytime in the first week. Include only cohorts whose target day is on or before the single report.as_of_day. Count users, not events, and keep mature cohorts with zero retained users. Return signup_day, cohort_size, retained_users, retention_pct as text with exactly two decimals (for example 50.00). Order by signup_day. Dates are valid ISO YYYY-MM-DD; activity can contain duplicates or events after the report date.

Schema (all columns are NOT NULL unless explicitly nullable):

CREATE TABLE users (user_id INTEGER PRIMARY KEY, signup_day TEXT NOT NULL);
CREATE TABLE activity (user_id INTEGER NOT NULL, day TEXT NOT NULL);
CREATE TABLE report (as_of_day TEXT NOT NULL);

Write one read-only SQLite query. The tables are already populated. Return exactly the requested columns and ordering, with no headers. Empty input produces no rows unless specified otherwise.

Example setup:

INSERT INTO report VALUES ('2024-01-08'); INSERT INTO users VALUES (1,'2024-01-01'),(2,'2024-01-01'); INSERT INTO activity VALUES (1,'2024-01-08'),(1,'2024-01-08');

Expected output:

2024-01-01|2|1|50.00

Timebox: 9 minutes. Focus on correctness at boundaries and duplicate handling.

Sample tests

Test #1Duplicate events
Input: "CREATE TABLE users (user_id INTEGER PRIMARY KEY, signup_day TEXT NOT NULL);\nCREATE TABLE activity (user_id INTEGER NOT NULL, day TEXT NOT NULL);\nCREATE TABLE report (as_of_day TEXT NOT NULL);\nINSERT INTO report VALUES ('2024-01-08'); INSERT INTO users VALUES (1,'2024-01-01'),(2,'2024-01-01'); INSERT INTO activity VALUES (1,'2024-01-08'),(1,'2024-01-08');"
Output: "2024-01-01|2|1|50.00"
Test #2Exclude immature cohort
Input: "CREATE TABLE users (user_id INTEGER PRIMARY KEY, signup_day TEXT NOT NULL);\nCREATE TABLE activity (user_id INTEGER NOT NULL, day TEXT NOT NULL);\nCREATE TABLE report (as_of_day TEXT NOT NULL);\nINSERT INTO report VALUES ('2024-01-08'); INSERT INTO users VALUES (1,'2024-01-01'),(2,'2024-01-02'); INSERT INTO activity VALUES (2,'2024-01-09');"
Output: "2024-01-01|1|0|0.00"