Premium problem89. Cohort Retention Matrix

Hard Locked

users(user_id, signup_date) and activity(user_id, activity_date)

Build a long-form retention matrix. For every signup cohort month and every month_number from 0 to 6, return the cohort size, how many of those users were active in that relative calendar month, and the percentage.

Month 0 is the signup month itself, so it is not automatically 100 percent: somebody can sign up and never do anything.

Return cohort_month as 'YYYY-MM', month_number, cohort_size, retained_users and retention_pct rounded to two decimals, ordered by cohort then month number. All seven rows appear for every cohort, including the ones whose relative months lie in the future of the data.

The month numbers have to come from somewhere, since a cohort with no month-4 activity still needs its month-4 row.

Tables

activity

user_id  activity_date
-------  -------------
1        2026-01-06
1        2026-02-06
1        2026-03-06
2        2026-01-21
2        2026-03-21
4        2026-02-11
4        2026-02-12

users

user_id  signup_date
-------  -----------
1        2026-01-05
2        2026-01-20
3        2026-01-25
4        2026-02-10

Expected result

cohort_month  month_number  cohort_size  retained_users  retention_pct
------------  ------------  -----------  --------------  -------------
2026-01       0             3            2               66.67
2026-01       1             3            1               33.33
2026-01       2             3            2               66.67
2026-01       3             3            0               0.00
2026-01       4             3            0               0.00
2026-01       5             3            0               0.00
2026-01       6             3            0               0.00
2026-02       0             1            1               100.00
... 6 more row(s)

Premium problem

This one's part of Premium. Unlock the full MySQL track plus every other premium problem on the site.

Write one SELECT query