Retention Analysis and Cohort Tracking: SQL Methodology from the Data Engineer Handbook

Retention analysis and cohort tracking measure user engagement over time by grouping users based on their first activity date and calculating the percentage who return in subsequent periods using SQL window functions.

The DataExpert-io/data-engineer-handbook repository provides a production-ready SQL methodology for performing retention analysis and cohort tracking on large-scale event data. This approach leverages standard SQL window functions and conditional aggregation to transform raw event logs into actionable cohort matrices directly inside your data warehouse, eliminating the need for external processing tools.

Step 1: Define the Event Table Structure

Before calculating retention, establish an events table that captures every user interaction. According to the schema defined in intermediate-bootcamp/materials/2-fact-data-modeling/tables/events.sql, this table requires at minimum:

  • user_id: Unique identifier for each user
  • event_timestamp: Timestamp of the action
  • event_name: Classification of the event (e.g., "login", "purchase")

This foundational table serves as the single source of truth for all subsequent cohort calculations.

Step 2: Create First-Touch Cohorts

The methodology anchors each user to their cohort date—the date of their first recorded event. In intermediate-bootcamp/materials/4-applying-analytical-patterns/lecture-lab/retention_analysis.sql, this is implemented using a MIN() aggregation to assign the cohort identifier:

SELECT 
    user_id, 
    MIN(event_timestamp) AS cohort_date 
FROM events 
GROUP BY user_id;

This query assigns every user to a specific cohort based on their initial activity, typically their first login or purchase date, which becomes the baseline for all retention measurements.

Step 3: Calculate Event Age Relative to Cohort

To track retention over time, compute the age of each event—the number of days elapsed since the user's cohort date. The retention_analysis.sql file uses DATEDIFF to create this metric:

SELECT 
    *, 
    DATEDIFF('day', cohort_date, event_timestamp) AS age 
FROM events_with_cohort;

This age column indicates which period of the user lifecycle each event belongs to, enabling period-over-period comparisons and lifecycle analysis.

Step 4: Aggregate Active Users by Cohort and Age

Next, group the data by cohort_date and age to count distinct active users in each time bucket. This aggregation, performed in the same retention analysis script, reveals how many users from each original cohort remain engaged:

SELECT 
    cohort_date, 
    age, 
    COUNT(DISTINCT user_id) AS active_users 
FROM events_with_age 
GROUP BY cohort_date, age 
ORDER BY cohort_date, age;

This step transforms individual event records into summary statistics that show retention decay curves for each cohort.

Step 5: Pivot into a Retention Matrix

Convert the aggregated rows into a readable matrix where rows represent cohorts and columns represent ages (days or weeks). The handbook implements this pivot using conditional aggregation with CASE statements inside MAX() aggregates:

SELECT 
    cohort_date, 
    MAX(CASE WHEN age = 0 THEN active_users END) AS day_0,
    MAX(CASE WHEN age = 1 THEN active_users END) AS day_1,
    MAX(CASE WHEN age = 7 THEN active_users END) AS day_7
FROM aggregated 
GROUP BY cohort_date;

This structure produces a retention curve that makes drop-off points immediately visible across different user cohorts, allowing product teams to identify when users typically disengage.

Step 6: Integrate with Business Metrics

For comprehensive growth accounting, join the retention matrix with revenue or other KPI tables. The intermediate-bootcamp/materials/4-applying-analytical-patterns/lecture-lab/growth_accounting.sql file demonstrates this integration:

SELECT 
    r.cohort_date, 
    r.day_7, 
    rev.total_revenue 
FROM retention_matrix r 
JOIN revenue_by_cohort rev 
    ON r.cohort_date = rev.cohort_date;

This combination enables analysis of how retention correlates with monetization across different user segments, providing a complete view of cohort value beyond simple activity counts.

Summary

Frequently Asked Questions

How do you define a user cohort in SQL?

A user cohort is defined by the date of their first recorded event, calculated using MIN(event_timestamp) GROUP BY user_id as implemented in intermediate-bootcamp/materials/4-applying-analytical-patterns/lecture-lab/retention_analysis.sql. This first-touch date becomes the cohort identifier that anchors all subsequent retention calculations and lifecycle analysis.

What SQL functions are required for retention analysis?

The methodology requires window functions (MIN() OVER or MIN() GROUP BY) to establish cohort dates, date arithmetic functions (DATEDIFF) to calculate event age, and conditional aggregation (CASE WHEN inside MAX() or SUM() functions) to pivot results into retention matrices. These standard SQL functions are available in Snowflake, BigQuery, Redshift, and PostgreSQL.

Can this methodology handle billions of events?

Yes. The SQL-based approach in the Data Engineer Handbook is designed for scalability, operating entirely within the data warehouse compute layer. By performing aggregation and pivoting using standard SQL rather than extracting data to external tools, the methodology minimizes data movement overhead and efficiently processes large-scale event logs.

How do you visualize retention curves from SQL output?

While the handbook focuses on SQL generation, the resulting pivot table can be exported to BI tools like Looker or Power BI, or plotted using Python (Matplotlib/Seaborn) or R. The matrix format—where rows represent cohorts and columns represent days or weeks—is optimized for heat-map style visualizations that highlight retention patterns and compare cohort performance over time.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →