Drugs and formularies
Medicaid State Drug Utilization (by state × NDC × quarter)
Rows
N/A
Columns
30
History
2020-Q1 (effective_period_start 2020-01-01) to 2024-Q4 (effective_period_start 2024-10-01); 20 consecutive quarters, ~1.2-1.3M rows each
Card
yesgrain, traps, filters
Typed tools
2
What it is
- 1CMS State Drug Utilization Data (SDUD): quarterly counts of Medicaid-covered outpatient drug prescriptions, units dispensed, and dollars reimbursed, broken out by state, drug package (NDC-11), and Medicaid program type (fee-for-service vs managed care).
- 2It is the public record of what state Medicaid programs actually paid for drugs, used as a public benchmark/denominator for drug cost and utilization analysis.
Grain
| Key | Grain |
|---|---|
utilization_typestatendc11data_yeardata_quarter |
|
How to read it
- 1National 2024 spend on a specific drug across all of Medicaid: SELECT data_year, data_quarter, SUM(total_amount_reimbursed_usd) AS spend, SUM(number_of_prescriptions) AS rx FROM drug_silver.fact_drug_medicaid_utilization WHERE state='XX' AND data_year=2024 AND suppression_used=false AND ndc11='<ndc>' GROUP BY data_year, data_quarter; — returns quarterly Medicaid-paid dollars and Rx counts for that drug package nationally (use state='XX' for national, or state<>'XX' grouped by state for a state breakdown), and SUM utilization_type FFSU+MCOU for the full program.
Traps
- 1HALF THE TABLE HAS NO NUMBERS: suppression_used=true on 12.78M rows (~49.5%) and on those EVERY metric (units_reimbursed, number_of_prescriptions, all *_amount_reimbursed_usd) is NULL — CMS privacy-suppressed small cells. Always filter WHERE suppression_used=false (or guard NULLs) before SUM/AVG, and remember unsuppressed rows always have >=11 prescriptions, so low-volume drugs are systematically missing.
- 2state='XX' IS THE NATIONAL ROLL-UP, NOT A STATE. Including it alongside per-state rows double-counts. Worse, XX is NOT the simple sum of the visible state rows: for 2023-Q1 unsuppressed, XX total=$27.86B vs sum-of-states=$26.14B, because the national figure also absorbs cells that were suppressed at the state level. Pick state<>'XX' for state analysis OR state='XX' for national totals — never mix, and don't reconstruct national by summing states (you'll undercount).
- 3GRAIN NEEDS BOTH utilization_type AND state. ndc11 alone is far from unique (71,806 distinct vs 25.8M rows); dropping utilization_type drops to 19.16M distinct (FFSU and MCOU rows collide on the same drug/state/quarter), and dropping state collapses to 1.56M. The full minimal key is (utilization_type, state, ndc11, data_year, data_quarter).
- 4labeler_code, product_code, package_size, observed_period, effective_period_start/end are all DERIVED, not independent: ndc11 is byte-for-byte concat(labeler_code,product_code,package_size) (0 mismatches) and the date columns are just the quarter boundaries from data_year/data_quarter. They add no grain and shouldn't be treated as separate keys. Note package_size is the NDC package CODE, not a dispensed quantity.
- 5product_name is unreliable free text — one ndc11 can appear under 12+ different name spellings across filings. Identify drugs by ndc11 (or labeler/product code), never by product_name.
- 6Provenance/SCD columns are inert in this snapshot: is_current=true, cms_vintage_sequence=1, parse_revision=1, vintage_tag='none', asserted_at=2026-05-16, drug_source_version_id=NULL are all single-valued. is_current filtering is currently a no-op and drug_source_version_id can't be joined yet — they're forward-compat scaffolding, so don't read meaning into them today. PR (Puerto Rico) data exists only from 2023 onward (52 states 2020-2022, 53 from 2023).
Columns (30)
| Column | Type | Meaning |
|---|---|---|
utilization_type | string | Medicaid program channel. EXACTLY 2 values: FFSU = Fee-For-Service Utilization (12.30M rows), MCOU = Managed Care Org Utilization (13.51M rows). Part of the grain — the same drug/state/quarter appears once per channel. Sum both for total Medicaid; do not assume one. |
state | string | 2-letter postal code of the state Medicaid program. 53 distinct values: 50 states + DC + PR (Puerto Rico, appears only from 2023) + 'XX'. 'XX' (1.56M rows) is the CMS NATIONAL aggregate, NOT a state — see gotchas. Part of grain. |
ndc11 | string | 11-digit National Drug Code identifying the exact drug package (labeler+product+package). 71,806 distinct. Always exactly = concat(labeler_code, product_code, package_size) (0 mismatches). The drug-join key. Part of grain. |
data_year | int | Calendar year of the utilization quarter (2020-2024). Part of grain; redundant with effective_period_start's year. |
data_quarter | int | Calendar quarter 1-4 of utilization. Part of grain; together with data_year fully determines all period columns. |
labeler_code | string | First 5 digits of the NDC = the drug labeler/manufacturer (FDA labeler code). 1,069 distinct. Derived from ndc11; descriptive, not independent grain. |
product_code | string | NDC product segment, the 4 digits after the labeler code (drug+strength+form). 7,182 distinct. Derived from ndc11; descriptive only. |
package_size | string | NDC package-size segment (trailing digits of the NDC, the package code — NOT a quantity/volume). Derived from ndc11; descriptive only. |
product_name | string | CMS-reported short drug name (free text, often truncated e.g. 'TRIAMCINOL','CLOBETASOL'). NOT stable per NDC — a single ndc11 can carry 12+ different spellings across filings. Use ndc11 to identify the drug, never product_name. |
suppression_used | boolean | CMS privacy flag. true (12.78M rows, ~49.5%) = the cell was suppressed for low volume and ALL metric columns are NULL. false (13.03M rows) = metrics populated. This is the single biggest data-handling fact: half the rows have no numbers. |
units_reimbursed | double | Total drug units (e.g. tablets/mL) reimbursed in the quarter. double. NULL when suppression_used=true. Range on populated rows: 0.003 to 6.15e8. No negatives observed. |
number_of_prescriptions | int | Count of reimbursed prescription claims (Rx) for that drug/state/channel/quarter. int. NULL when suppressed. On populated rows MIN=11 — confirming CMS suppresses any cell with <11 Rx. Max 1,812,525. |
total_amount_reimbursed_usd | double | Total dollars reimbursed for the drug (Medicaid + non-Medicaid). double USD. NULL when suppressed. 0 to 6.27e8, no negatives. Equals medicaid + non_medicaid (matches for all but 8 rounding rows). |
medicaid_amount_reimbursed_usd | double | Portion of total reimbursed paid by the state Medicaid program itself. double USD. NULL when suppressed. |
non_medicaid_amount_reimbursed_usd | double | Portion of total reimbursed paid by third parties / patient cost-share (non-Medicaid). double USD. NULL when suppressed. medicaid + non_medicaid = total. |
observed_period | date | date = first day of the utilization quarter. Fully derived from data_year/data_quarter (e.g. 2021-Q4 -> 2021-10-01). Equals effective_period_start. |
asserted_at | date | date the ingest pipeline asserted this snapshot. Constant 2026-05-16 for every row (single load). Lineage scaffolding, not analytic. |
effective_period_start | date | date = first day of the quarter the utilization covers (= observed_period). The profiler's temporal column. Derived from year+quarter. |
effective_period_end | date | date = last day of the quarter (e.g. 2020-03-31, 2020-06-30). Derived from year+quarter; with start it bounds the quarter. |
cms_vintage_sequence | int | Intended CMS restatement-vintage ordinal. Constant = 1 for all rows (only one vintage loaded). Currently carries no discriminating value. |
parse_revision | int | Parser revision number. Constant = 1 for all rows. Lineage scaffolding. |
parser_artifact_hash | string | SHA-256 of the parser code/artifact that produced the row (lineage). Single value observed across the load. |
source_url | string | CMS download URL of the annual source CSV. 5 distinct values, one per year: https://download.medicaid.gov/data/StateDrugUtilizationData-YYYY.csv (2020-2024). |
sha256_content_hash | string | SHA-256 of the source CSV content (the bronze object), for provenance/dedup. |
source_id | string | Logical source identifier. Constant 'medicaid_sdud' for every row — single-source table. |
is_current | boolean | SCD-2 current-version flag. true for 100% of rows (no superseded versions yet). Filtering on it is a no-op today but keep it for forward compatibility. |
bronze_object_key | string | S3 key of the raw bronze CSV this row was parsed from (lineage), e.g. drug/bronze/medicaid_sdud/2021/<hash>-StateDrugUtilizationData-2021.csv. |
s3_version_id | string | S3 object version id of the bronze source file (lineage). |
vintage_tag | string | Human vintage label. Constant 'none' for all rows (no vintage tagging applied yet). |
drug_source_version_id | string | FK to a drug source-version registry. NULL for every row currently — not yet populated; do not rely on it for joins. |
Query it
describe_data_source(source_fqn="drug_silver.fact_drug_medicaid_utilization") # the card, live query_substrate(sql="SELECT * FROM drug_silver.fact_drug_medicaid_utilization WHERE utilization_type = '<value>' AND state = '<value>' AND ndc11 = '<value>' AND data_year = '<value>' AND data_quarter = '<value>' LIMIT 100")
| Item | Value |
|---|---|
| Typed tools that read it | ira_mfp_exposure, recall_spend_window |
| Identity key | ndc11 |
| Join | how_to_join(source_fqn="drug_silver.fact_drug_medicaid_utilization") |
| Raw door | Athena (read-only via query_substrate): drug_silver.fact_drug_medicaid_utilization |
This page as markdown: /docs-md/data/drug_silver_fact_drug_medicaid_utilization.md · every page in one file: /llms-full.txt