ICD-10 Codes: Complete Guide to Diagnosis Classification

Everything you need to know about ICD-10-CM diagnosis codes, database design, code structure, lookup methods, and billing integration.

What is ICD-10?

ICD-10 (International Classification of Diseases, 10th Revision) is a medical classification system maintained by the World Health Organization (WHO) for coding diagnoses, symptoms, and procedures. In the United States, ICD-10-CM (Clinical Modification) is used for diagnosis coding in all healthcare settings.

Key Facts About ICD-10

  • Total Codes: 70,000+ diagnosis codes (ICD-10-CM)
  • Code Length: 3-7 alphanumeric characters
  • Implementation Date: October 1, 2015 (US)
  • Updates: Annual updates every October 1st
  • Maintained By: WHO (ICD-10), CDC/CMS (ICD-10-CM)

ICD-10 Code Structure

Code Format

ICD-10-CM codes consist of 3-7 characters:

Example: E11.65

  • E = Category (Endocrine diseases)
  • 11 = Etiology (Type 2 diabetes mellitus)
  • . = Decimal point (always after 3rd character)
  • 6 = Subcategory (with complications)
  • 5 = Extension (hyperglycemia)

Full Description: Type 2 diabetes mellitus with hyperglycemia

Code Categories (First Character)

RangeCategoryExamples
A00-B99Infectious diseasesTuberculosis, HIV, COVID-19
C00-D49NeoplasmsCancer, tumors
E00-E89Endocrine/metabolicDiabetes, thyroid disorders
I00-I99Circulatory systemHypertension, heart disease
J00-J99Respiratory systemAsthma, pneumonia, COPD
M00-M99MusculoskeletalArthritis, back pain
S00-T88Injury & poisoningFractures, burns, overdoses
Z00-Z99Factors influencing healthScreening, preventive care

Database Schema for ICD-10 Codes

ICD-10 Master Table

CREATE TABLE icd10_codes (
  icd10_cd VARCHAR(10) PRIMARY KEY,
  
  -- Code Details
  icd10_desc VARCHAR(500) NOT NULL,  -- Full description
  short_desc VARCHAR(100),            -- Abbreviated description
  
  -- Code Structure
  category VARCHAR(3),                -- First 3 characters
  subcategory VARCHAR(1),             -- 4th character
  extension VARCHAR(3),               -- 5th-7th characters
  
  -- Classification
  chapter_nbr INT,                    -- Chapter (1-21)
  chapter_desc VARCHAR(200),          -- Chapter description
  section_range VARCHAR(20),          -- Code range (e.g., 'A00-B99')
  
  -- Code Type
  is_billable BOOLEAN DEFAULT FALSE,  -- Can be billed
  is_header BOOLEAN DEFAULT FALSE,    -- Header/category code
  
  -- Laterality & 7th Character
  requires_7th_char BOOLEAN,          -- Needs 7th character
  laterality VARCHAR(20),             -- Left, Right, Bilateral
  
  -- Version Control
  eff_dt DATE NOT NULL,               -- Effective date
  exp_dt DATE,                        -- Expiration date
  version VARCHAR(10),                -- Annual version (e.g., '2024')
  
  -- Metadata
  last_upd_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Indexes
CREATE INDEX idx_icd10_cat ON icd10_codes(category);
CREATE INDEX idx_icd10_desc ON icd10_codes USING gin(to_tsvector('english', icd10_desc));
CREATE INDEX idx_icd10_billable ON icd10_codes(is_billable) WHERE is_billable = TRUE;
CREATE INDEX idx_icd10_version ON icd10_codes(version, eff_dt);

Patient Diagnosis Table

CREATE TABLE patient_diagnoses (
  pt_diag_id VARCHAR(50) PRIMARY KEY,
  
  -- Patient & Encounter
  pt_id VARCHAR(50) NOT NULL,
  enc_id VARCHAR(50),                 -- Encounter ID
  
  -- Diagnosis
  icd10_cd VARCHAR(10) NOT NULL,
  diag_desc VARCHAR(500),             -- Description
  
  -- Diagnosis Attributes
  diag_typ VARCHAR(20),               -- Principal, Secondary, Admitting
  diag_poa VARCHAR(1),                -- Present on Admission (Y/N/U/W)
  diag_seq INT,                       -- Diagnosis sequence/rank
  
  -- Clinical Details
  onset_dt DATE,                      -- Date of onset
  resolved_dt DATE,                   -- Date resolved
  diag_sts VARCHAR(20),               -- Active, Resolved, Chronic
  
  -- Provider
  diag_prvdr_npi VARCHAR(10),         -- Diagnosing provider
  diag_dt DATE NOT NULL,              -- Date diagnosed
  
  -- Metadata
  crtd_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  upd_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  
  FOREIGN KEY (pt_id) REFERENCES patients(pt_id),
  FOREIGN KEY (icd10_cd) REFERENCES icd10_codes(icd10_cd)
);

-- Indexes
CREATE INDEX idx_pt_diag_pt ON patient_diagnoses(pt_id);
CREATE INDEX idx_pt_diag_enc ON patient_diagnoses(enc_id);
CREATE INDEX idx_pt_diag_cd ON patient_diagnoses(icd10_cd);
CREATE INDEX idx_pt_diag_dt ON patient_diagnoses(diag_dt);
CREATE INDEX idx_pt_diag_typ ON patient_diagnoses(diag_typ);

Common ICD-10 Abbreviations

AbbreviationFull TermDescription
icd10_cdICD-10 codeDiagnosis code
diag_cddiagnosis codeGeneral diagnosis code field
diag_descdiagnosis descriptionDiagnosis text description
pdxprincipal diagnosisPrimary diagnosis
sdxsecondary diagnosisAdditional diagnoses
poapresent on admissionPOA indicator (Y/N/U/W)
dx_seqdiagnosis sequenceOrder of diagnosis (1, 2, 3...)

ICD-10 Coding Rules

1. Code to the Highest Specificity

Always use the most specific code available (up to 7 characters):

  • E11 - Too general (Type 2 diabetes, unspecified)
  • E11.65 - Specific (Type 2 diabetes with hyperglycemia)

2. Billable vs Non-Billable Codes

Only codes at the highest level of specificity can be billed:

  • I10 (3 chars) - Billable if no further specificity available
  • E11.6 (4 chars) - NOT billable (subcategory only)
  • E11.65 (5 chars) - Billable (full specificity)

3. Placeholder 'X' Character

Some codes require 'X' as a placeholder to reach 7 characters:

  • T36.0X5A - Adverse effect of penicillins, initial encounter
  • X fills positions when no specific code exists

4. 7th Character Extensions

Injury codes (S00-T88) require a 7th character:

  • A - Initial encounter
  • D - Subsequent encounter
  • S - Sequela (late effect)

ICD-10 Lookup Queries

-- Search by keyword
SELECT icd10_cd, icd10_desc
FROM icd10_codes
WHERE to_tsvector('english', icd10_desc) @@ to_tsquery('english', 'diabetes & hypertension')
  AND is_billable = TRUE
ORDER BY icd10_cd;

-- Find all diabetes codes
SELECT icd10_cd, icd10_desc
FROM icd10_codes
WHERE category LIKE 'E1%'  -- Diabetes categories
  AND is_billable = TRUE
ORDER BY icd10_cd;

-- Get patient's active diagnoses
SELECT 
  pd.icd10_cd,
  ic.icd10_desc,
  pd.diag_dt,
  pd.diag_sts
FROM patient_diagnoses pd
JOIN icd10_codes ic ON pd.icd10_cd = ic.icd10_cd
WHERE pd.pt_id = 'PT123'
  AND pd.diag_sts = 'Active'
ORDER BY pd.diag_dt DESC;

-- Most common diagnoses
SELECT 
  pd.icd10_cd,
  ic.icd10_desc,
  COUNT(*) as diag_cnt
FROM patient_diagnoses pd
JOIN icd10_codes ic ON pd.icd10_cd = ic.icd10_cd
WHERE pd.diag_dt >= CURRENT_DATE - INTERVAL '1 year'
GROUP BY pd.icd10_cd, ic.icd10_desc
ORDER BY diag_cnt DESC
LIMIT 100;

ICD-9 to ICD-10 Mapping

General Equivalence Mappings (GEMs)

CMS provides crosswalk files for converting between ICD-9 and ICD-10:

CREATE TABLE icd9_to_icd10_map (
  map_id VARCHAR(50) PRIMARY KEY,
  
  icd9_cd VARCHAR(10),
  icd10_cd VARCHAR(10),
  
  -- Mapping Attributes
  map_typ VARCHAR(20),      -- Forward, Backward, Approximate
  scenario INT,             -- Mapping scenario
  choice_list INT,          -- Multiple choices indicator
  
  -- Flags
  is_exact_match BOOLEAN,
  is_approx_match BOOLEAN,
  
  eff_dt DATE,
  exp_dt DATE
);

-- Example mapping query
SELECT 
  i9.icd9_cd,
  i9.icd9_desc,
  m.icd10_cd,
  i10.icd10_desc,
  m.is_exact_match
FROM icd9_to_icd10_map m
JOIN icd9_codes i9 ON m.icd9_cd = i9.icd9_cd
JOIN icd10_codes i10 ON m.icd10_cd = i10.icd10_cd
WHERE i9.icd9_cd = '250.00';

Integration with Claims

EDI 837 Claims

ICD-10 codes appear in the HI segment of claims:

  • HI*ABK:E1165 - Principal diagnosis
  • HI*ABF:I10 - Secondary diagnosis
  • BK = Principal diagnosis qualifier
  • BF = Secondary diagnosis qualifier

Claims Database Integration

CREATE TABLE claim_diagnoses (
  clm_diag_id VARCHAR(50) PRIMARY KEY,
  
  clm_id VARCHAR(50) NOT NULL,
  
  -- Diagnosis
  icd10_cd VARCHAR(10) NOT NULL,
  diag_typ VARCHAR(20),         -- Principal, Secondary, Admitting
  diag_seq INT,                 -- Sequence on claim
  poa_ind VARCHAR(1),           -- Present on Admission
  
  -- POA Values: Y=Yes, N=No, U=Unknown, W=Undetermined, blank=Exempt
  
  FOREIGN KEY (clm_id) REFERENCES claims(clm_id),
  FOREIGN KEY (icd10_cd) REFERENCES icd10_codes(icd10_cd)
);

Best Practices

Data Quality

  • ✅ Validate ICD-10 codes against master table
  • ✅ Ensure codes are billable when required
  • ✅ Verify code is active for date of service
  • ✅ Check for required 7th characters
  • ✅ Validate POA indicators for inpatient claims

Annual Updates

  • ✅ Download updated ICD-10 files every October 1st
  • ✅ Update code master tables
  • ✅ Test system with new/modified codes
  • ✅ Communicate changes to coding staff

Performance Optimization

  • ✅ Index frequently searched columns (category, description)
  • ✅ Use full-text search for description lookups
  • ✅ Cache commonly used codes
  • ✅ Partition diagnosis tables by year

Common ICD-10 Examples

Frequently Used Codes

  • I10 - Essential (primary) hypertension
  • E11.9 - Type 2 diabetes without complications
  • E78.5 - Hyperlipidemia, unspecified
  • J44.9 - COPD, unspecified
  • M79.3 - Panniculitis, unspecified
  • Z00.00 - Encounter for general adult medical exam without abnormal findings
  • Z12.31 - Encounter for screening mammogram for malignant neoplasm of breast

Resources

Official ICD-10 Resources