HomeProjectsCertificationsContact
SQL

HR Analytics: Attrition & Compensation Equity

Window-function-heavy SQL analysis of 1,470 employee records to find who leaves, why overtime is the strongest attrition lever, and where pay compression hides.

DatasetIBM HR Analytics Employee Attrition (public)
Scale1,470 employees · 35 attributes · 16.1% attrition
ToolsPostgreSQL · Window Functions · PERCENTILE_CONT · CASE Pivots
View code & data on GitHub ↗

The Problem

HR leadership knew the headline attrition number (16.1%) but not its shape: which roles bleed fastest, whether overtime and compensation actually correlate with exits, and whether pay is internally consistent for the same role and experience level.

Everything here is answerable in pure SQL. The point of this project was to demonstrate that a well-structured query layer can replace a BI tool for the diagnostic phase: percentile pay bands, cohort comparisons, and multi-dimensional attrition cuts, all as reusable views.

1,470employee records
30.5%attrition with overtime
61.9%bottom-pay-quartile sales rep attrition
99pay compression flags (6.7%)

Approach

01

Attrition baseline and single-factor cuts

Established the 16.1% baseline, then built a reusable CASE-pivot pattern producing attrition rate by department, role, age band, and satisfaction level in one result set.

02

Overtime interaction analysis

Crossed overtime status with job role and work-life balance scores to test whether overtime's effect is uniform or concentrated in specific roles.

03

Compensation percentile bands

Used PERCENTILE_CONT and NTILE to build pay quartiles within each job role, comparing attrition in the bottom quartile vs top quartile of role-relative pay.

04

Pay compression detection

Window functions comparing each employee's salary against role-and-level medians flagged employees earning less than peers with several years less experience.

05

Tenure survival view

Built years-at-company attrition curves to identify the highest-risk tenure windows for intervention timing.

The Work

Representative excerpts from the analysis: the queries and transformations doing the heavy lifting. The full runnable project lives in the GitHub repo.

Attrition by role with role-relative pay quartilessql
WITH pay_quartiles AS (
  SELECT
    employee_number,
    job_role,
    monthly_income,
    attrition,
    NTILE(4) OVER (
      PARTITION BY job_role
      ORDER BY monthly_income
    ) AS pay_quartile_in_role
  FROM employees
)
SELECT
  job_role,
  COUNT(*)                                          AS headcount,
  ROUND(100.0 * AVG(CASE WHEN attrition = 'Yes'
        THEN 1 ELSE 0 END), 1)                      AS attrition_pct,
  ROUND(100.0 * AVG(CASE WHEN attrition = 'Yes'
        AND pay_quartile_in_role = 1
        THEN 1 ELSE 0 END) /
    NULLIF(AVG(CASE WHEN pay_quartile_in_role = 1
        THEN 1 ELSE 0 END), 0), 1)                  AS attrition_pct_bottom_pay_q
FROM pay_quartiles
GROUP BY job_role
ORDER BY attrition_pct DESC;
Pay compression: paid under the less-experienced mediansql
WITH role_level_median AS (
  SELECT
    job_role,
    job_level,
    PERCENTILE_CONT(0.5) WITHIN GROUP (
      ORDER BY monthly_income
    ) AS median_income
  FROM employees
  GROUP BY job_role, job_level
)
SELECT
  e.employee_number,
  e.job_role,
  e.total_working_years,
  e.monthly_income,
  m.median_income                       AS peer_median,
  ROUND(100.0 * (e.monthly_income - m.median_income)
        / m.median_income, 1)           AS pct_vs_peer_median
FROM employees e
JOIN role_level_median m
  ON  m.job_role  = e.job_role
  AND m.job_level = e.job_level
WHERE e.monthly_income < m.median_income * 0.85
  AND e.total_working_years >
      (SELECT AVG(total_working_years) FROM employees e2
       WHERE e2.job_role = e.job_role
         AND e2.job_level = e.job_level)
ORDER BY pct_vs_peer_median;

What the Data Shows

Attrition rate by job role

% of employees who left

Sales Representative
39.8%
Laboratory Technician
23.9%
Human Resources
19.1%
Sales Executive
17.5%
Research Scientist
16.1%
Manager
4.9%

Company baseline is 16.1%. One role runs at 2.5 times baseline while senior roles barely move, which points at role design rather than individuals.

Key Findings

Employees working overtime leave at 30.5% vs 10.4% without overtime. It is the largest controllable factor in the dataset, and it compounds: overtime plus a low work-life-balance score exceeds 45%.

Sales Representatives attrit at 39.8%, more than double the company average, while Research Directors and Managers sit near 3 to 5%.

Company-wide, bottom-quartile earners leave at 19.5% vs 14.6% for the top quartile. Inside the highest-churn role it explodes: bottom-quartile Sales Representatives leave at 61.9%.

99 employees (6.7%) earn 15%+ below the median of colleagues at the same role and level despite above-average experience, classic compression created by out-hiring.

Attrition peaks in years 0-2 (43% of all company exits) and again around the 5-year mark, suggesting two distinct intervention windows.

Low environment-satisfaction employees churn at 25.3% vs 13.4% for satisfied ones, a cheap survey signal that predicts real exits.

Recommendations

Overtime audit for the top 3 affected roles

Overtime attrition risk is concentrated, not uniform. Rebalancing workload for lab technicians and sales reps targets the 45%+ compound-risk pocket directly.

Compression review before annual raises

The flagged 6% cohort (paid 15%+ under peer median) is a defined, budgetable list. Correcting it costs far less than replacing those employees.

Restructure sales rep incentives

A 39.8% attrition rate in one role points to a role design problem (quota and base mix), not individual performance issues.

Year-2 and year-5 stay interviews

Timing retention conversations to the two attrition peaks beats annual blanket surveys on both cost and effect.