HEDIS Measures Guide
Complete guide to HEDIS (Healthcare Effectiveness Data and Information Set) quality measures. Learn database design, measure calculation, numerator/denominator logic, and Star Ratings.
What are HEDIS Measures?
HEDIS (Healthcare Effectiveness Data and Information Set) is a comprehensive set of standardized performance measures developed by the National Committee for Quality Assurance (NCQA). Health plans, including Medicare Advantage and commercial insurers, use HEDIS to measure quality of care and service.
HEDIS measures cover prevention, acute and chronic disease management, behavioral health, and patient experience. Results drive quality improvement, bonus payments, and consumer choice through Star Ratings.
Common HEDIS Measures
HbA1c Control (HBD)
Percentage of diabetic patients with HbA1c poor control (>9.0%)
Numerator: Members with most recent HbA1c >9.0%
Lower is better (fewer patients with poor control)
Breast Cancer Screening (BCS)
Percentage of women who had mammogram to screen for breast cancer
Numerator: Women with mammogram in last 2 years
Higher is better (more women screened)
Colorectal Cancer Screening (COL)
Percentage of adults who had appropriate screening for colorectal cancer
Numerator: Members with colonoscopy (10 yrs), FIT (1 yr), or Cologuard (3 yrs)
Higher is better
Controlling High Blood Pressure (CBP)
Percentage of patients with hypertension whose BP is adequately controlled
Numerator: BP <140/90 mmHg
Higher is better
HEDIS Database Schema
-- HEDIS Measure Definitions CREATE TABLE hedis_measure ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Measure Identification measure_code VARCHAR(10) UNIQUE NOT NULL, -- BCS, HBD, COL, etc. measure_name VARCHAR(255) NOT NULL, measure_domain VARCHAR(100), -- Effectiveness, Access, etc. -- Measure Details description TEXT, numerator_definition TEXT, denominator_definition TEXT, exclusion_criteria TEXT, -- Calculation higher_is_better BOOLEAN, -- Metadata ncqa_year INTEGER, -- HEDIS year active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT NOW() ); -- Patient Measure Attribution CREATE TABLE patient_measure_attribution ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), patient_id UUID NOT NULL, measure_code VARCHAR(10) REFERENCES hedis_measure(measure_code), measurement_year INTEGER NOT NULL, -- Eligibility in_denominator BOOLEAN DEFAULT FALSE, denominator_date DATE, -- Exclusions is_excluded BOOLEAN DEFAULT FALSE, exclusion_reason VARCHAR(255), -- Numerator Compliance in_numerator BOOLEAN DEFAULT FALSE, numerator_date DATE, numerator_value VARCHAR(100), -- e.g., HbA1c value -- Data Sources data_source VARCHAR(50), -- claims, lab, EHR evidence_date DATE, -- Status status VARCHAR(50), -- pending, complete, gap last_calculated TIMESTAMP, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), UNIQUE(patient_id, measure_code, measurement_year) ); CREATE INDEX idx_measure_attr_patient ON patient_measure_attribution(patient_id); CREATE INDEX idx_measure_attr_measure ON patient_measure_attribution(measure_code); CREATE INDEX idx_measure_attr_year ON patient_measure_attribution(measurement_year); CREATE INDEX idx_measure_attr_status ON patient_measure_attribution(status); -- Care Gaps (Patients Not Meeting Measures) CREATE TABLE care_gap ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), patient_id UUID NOT NULL, measure_code VARCHAR(10) REFERENCES hedis_measure(measure_code), gap_year INTEGER NOT NULL, -- Gap Details gap_type VARCHAR(50), -- overdue, never done gap_description TEXT, recommended_action TEXT, -- Outreach outreach_status VARCHAR(50), -- pending, contacted, scheduled, closed outreach_date DATE, outreach_method VARCHAR(50), -- Closure gap_closed_date DATE, closure_method VARCHAR(100), -- appointment, lab, etc. -- Priority priority VARCHAR(20), -- high, medium, low created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_gap_patient ON care_gap(patient_id); CREATE INDEX idx_gap_measure ON care_gap(measure_code); CREATE INDEX idx_gap_status ON care_gap(outreach_status); -- Measure Results (Aggregated) CREATE TABLE measure_results ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), measure_code VARCHAR(10) REFERENCES hedis_measure(measure_code), measurement_year INTEGER NOT NULL, -- Results by Segment (optional) provider_id UUID, plan_id UUID, region VARCHAR(100), -- Calculation denominator_count INTEGER NOT NULL, numerator_count INTEGER NOT NULL, exclusion_count INTEGER, -- Rate measure_rate DECIMAL(5,2), -- Percentage -- Benchmarks ncqa_percentile INTEGER, -- 10th, 25th, 50th, 75th, 90th -- Metadata calculation_date DATE NOT NULL, created_at TIMESTAMP DEFAULT NOW(), UNIQUE(measure_code, measurement_year, provider_id, plan_id) ); CREATE INDEX idx_results_measure ON measure_results(measure_code); CREATE INDEX idx_results_year ON measure_results(measurement_year);
Measure Calculation Logic
Step-by-Step Calculation
Find all patients who meet age, diagnosis, and enrollment criteria for the measure period
Remove patients with valid exclusion criteria (hospice, bilateral mastectomy, etc.)
Count patients who met the measure criteria (screening done, test result in range)
Rate = (Numerator / [Denominator - Exclusions]) × 100
SQL Query Examples
Calculate Breast Cancer Screening Rate
WITH eligible_patients AS (
SELECT patient_id
FROM patient_measure_attribution
WHERE measure_code = 'BCS'
AND measurement_year = 2024
AND in_denominator = TRUE
AND is_excluded = FALSE
),
numerator_patients AS (
SELECT patient_id
FROM patient_measure_attribution
WHERE measure_code = 'BCS'
AND measurement_year = 2024
AND in_numerator = TRUE
)
SELECT
COUNT(DISTINCT ep.patient_id) as denominator,
COUNT(DISTINCT np.patient_id) as numerator,
ROUND(100.0 * COUNT(DISTINCT np.patient_id) / COUNT(DISTINCT ep.patient_id), 2) as rate
FROM eligible_patients ep
LEFT JOIN numerator_patients np ON ep.patient_id = np.patient_id;Find Patients with Open Care Gaps
SELECT
p.mrn,
p.first_name || ' ' || p.last_name as patient_name,
hm.measure_name,
cg.gap_description,
cg.recommended_action,
cg.priority
FROM care_gap cg
JOIN patient p ON cg.patient_id = p.id
JOIN hedis_measure hm ON cg.measure_code = hm.measure_code
WHERE cg.gap_year = 2024
AND cg.outreach_status IN ('pending', 'contacted')
AND cg.gap_closed_date IS NULL
ORDER BY
CASE cg.priority
WHEN 'high' THEN 1
WHEN 'medium' THEN 2
ELSE 3
END,
p.last_name;HEDIS & Star Ratings
How HEDIS Drives Star Ratings
Medicare Advantage Star Ratings (1-5 stars) include ~40 measures, with many derived from HEDIS. Higher stars = quality bonus payments (up to 5% increase) + increased enrollment.
- 4+ stars: Eligible for quality bonus payments
- 5 stars: Can enroll members year-round (not just open enrollment)
- 3 stars or below: Risk of contract termination
Key HEDIS measures in Stars: Diabetes care (HbA1c, eye exam, kidney test), controlling blood pressure, medication adherence, breast cancer screening