Headcount Trends & Attrition Analysis

Headcount Trends & Attrition Analysis

Headcount analysis tracks how many people work here and how many leave. Attrition rate = terminations / average headcount × 100. Voluntary vs involuntary attrition have very different organizational meanings.

-- Monthly attrition rate by department (last 12 months)
WITH monthly_terms AS (
    SELECT
        dept_id,
        DATE_TRUNC('month', termination_date)          AS term_month,
        COUNT(*)                                        AS terminations,
        COUNT(*) FILTER (WHERE termination_reason = 'voluntary') AS voluntary,
        COUNT(*) FILTER (WHERE termination_reason != 'voluntary'
                           AND termination_reason IS NOT NULL)   AS involuntary
    FROM hr_employees
    WHERE termination_date >= NOW() - INTERVAL '12 months'
    GROUP BY dept_id, DATE_TRUNC('month', termination_date)
),
monthly_hc AS (
    SELECT dept_id, snapshot_month, headcount
    FROM hr_headcount_snapshots
    WHERE snapshot_month >= DATE_TRUNC('month', NOW() - INTERVAL '12 months')
)
SELECT
    d.name                                              AS department,
    TO_CHAR(hc.snapshot_month, 'YYYY-MM')               AS month,
    hc.headcount,
    COALESCE(mt.terminations, 0)                        AS terminations,
    COALESCE(mt.voluntary, 0)                           AS voluntary,
    COALESCE(mt.involuntary, 0)                         AS involuntary,
    ROUND(100.0 * COALESCE(mt.terminations, 0)
          / NULLIF(hc.headcount, 0), 2)                 AS attrition_rate_pct
FROM monthly_hc hc
JOIN hr_departments d ON d.id = hc.dept_id
LEFT JOIN monthly_terms mt
    ON mt.dept_id = hc.dept_id AND mt.term_month = hc.snapshot_month
ORDER BY d.name, hc.snapshot_month;

Purchase this course to unlock the full lesson.

Sign up