You are given PostgreSQL tables user_profile(user_id, signup_ts, country, is_employee, is_test), user_events(user_id, event_ts, event_type, revenue, platform), and user_merges(child_user_id, parent_user_id, merged_ts). Using only CTEs and window functions, write a single SQL query that returns monthly cohort retention for cohorts Jan–Mar 2025 and months k=0..3 with columns: cohort_month (YYYY-MM-01), month_number (k), users_in_cohort, retained_users, crr = retained_users::decimal/users_in_cohort. Rules and edge cases: 1) Consolidate identities: if a child_user_id merges into a parent_user_id, treat ALL of the child’s events (before and after merged_ts) as belonging to the parent. 2) Eligible cohort users are those with country = 'US', is_employee = false, is_test = false; cohort is date_trunc('month', signup_ts) (UTC). 3) A user is ACTIVE in a calendar month if they have ≥1 event with event_type IN ('app_open','purchase') in that month; months containing only 'refund' events do not count as active. 4) A user is RETAINED in cohort month k if they are active in that month AND the gap between their first active event in that month and their previous non-refund event (on the consolidated identity’s timeline) is ≤ 35 days; compute gaps using LAG() ordered by event_ts. 5) After the first month where the gap from the prior non-refund event exceeds 60 days, do not count the user as retained in subsequent months. 6) Treat timestamps as UTC; do not use temp tables. Include LAG() at least once. Output sorted by cohort_month, month_number. Small sample data:
user_profile
+---------+---------------------+---------+-------------+---------+
| user_id | signup_ts | country | is_employee | is_test |
+---------+---------------------+---------+-------------+---------+
| 1 | 2025-01-10 09:00:00 | US | f | f |
| 2 | 2025-01-20 12:00:00 | US | f | f |
| 3 | 2025-02-02 08:00:00 | US | f | f |
| 4 | 2025-02-15 10:00:00 | US | t | f |
| 5 | 2025-02-20 11:00:00 | GB | f | t |
+---------+---------------------+---------+-------------+---------+
user_events
+---------+---------------------+------------+---------+----------+
| user_id | event_ts | event_type | revenue | platform |
+---------+---------------------+------------+---------+----------+
| 1 | 2025-01-10 10:00:00 | app_open | 0.00 | ios |
| 1 | 2025-02-05 09:00:00 | purchase | 9.99 | ios |
| 1 | 2025-02-06 12:00:00 | refund | -9.99 | ios |
| 1 | 2025-03-20 08:00:00 | app_open | 0.00 | ios |
| 2 | 2025-01-21 12:00:00 | app_open | 0.00 | android |
| 2 | 2025-03-01 10:00:00 | app_open | 0.00 | android |
| 3 | 2025-02-10 14:00:00 | app_open | 0.00 | web |
| 3 | 2025-03-14 16:00:00 | app_open | 0.00 | web |
| 3 | 2025-05-20 09:00:00 | app_open | 0.00 | web |
| 4 | 2025-02-16 13:00:00 | app_open | 0.00 | ios |
| 5 | 2025-02-22 09:30:00 | app_open | 0.00 | android |
+---------+---------------------+------------+---------+----------+
user_merges
+---------------+----------------+---------------------+
| child_user_id | parent_user_id | merged_ts |
+---------------+----------------+---------------------+
| 2 | 1 | 2025-03-02 00:00:00 |
+---------------+----------------+---------------------+