▸ Data / HCRIS hospital financials / Dictionary

HCRIS Hospital Financials

Description

Full financial and operational detail from the Healthcare Cost Report Information System (HCRIS) — the annual cost report every Medicare-certified hospital in the US is required to file. One row per (CCN × fiscal year); a hospital with 20 years of filing history has 20 rows. This is the underlying cost-report line-item table (charges, costs, revenues, bed counts, workforce, balance sheet), not a search-index summary — it's the full financial history CMS/NBER-cleaned files provide, preferred here over a "latest per CCN" view because bulk-license buyers generally want the time series, not just the current snapshot.

  • Source: CMS Healthcare Cost Report Information System, via CMS/NBER cleaned cost-report files.
  • Refresh cadence: rolling, as CMS posts new/amended cost reports; ingestion cadence is not fixed-calendar.
  • Row count: 173,959
  • Vintage: 2026-05-26 (max ingested_at observed at export time)
  • Coverage: fiscal years 1996–2025, 10,138 distinct CCNs; 846 of them map to a publicly traded operator across 14 tickers (2026-08-29 crosswalk).

Table: hcris_hospital_financials

Snowflake: HEALTHPARSE_DATA.HCRIS_HOSPITAL_FINANCIALS.HCRIS_HOSPITAL_FINANCIALS

Column Type Description Notes
ccn VARCHAR CMS Certification Number — the 6-character federal ID for the hospital (facility-level primary identifier across virtually every CMS dataset). Not unique alone; unique with fy_end.
npi VARCHAR Linked organizational National Provider Identifier, when a match to the hospital's NPI record was made. Populated on 49,696 of 173,959 rows (~29%). Absent doesn't mean the hospital lacks an NPI — it means the ingestion-time link wasn't made.
provider_name VARCHAR Hospital name as filed on the cost report. 7,244 rows (~4%) hold the literal placeholder Unknown where the source file didn't carry a resolvable name.
street / city / state VARCHAR Mailing address on file with the cost report, as filed. city/state are null wherever provider_name is Unknown.
zip VARCHAR Verified 5-digit US ZIP, or NULL. Never a ZIP+4, never a trailing hyphen: the source ZIP+4 box is reduced to its 5-digit prefix and the +4 is dropped. The value is then checked against the Census 2020 ZCTA universe and against this row's own state; anything that fails either check is NULL. 161,378 of 173,959 rows populated (92.8%); 100% of those are a real ZIP consistent with state. 12,581 NULL = 7,281 blank at source + 4,584 CCN-in-ZIP + 359 ZIP/state contradiction + 351 not a real ZIP for that state + 6 unrecoverable. NULL means "not verified", not "no address" — city and state are still populated on most of those rows. Rule and reference file: see the zip section of the dictionaries README.
fy_begin / fy_end DATE Cost-report fiscal year start/end dates (hospital fiscal years are not calendar-aligned). fy_end is never null; fy_begin can be.
fy_end_year / fy_end_month SMALLINT Denormalized year/month of fy_end, for filtering without a date function. —
control_type VARCHAR Ownership/control category from the cost report (e.g. "Voluntary non-profit - Church", "Proprietary", "Government - State"). Mixed encoding: ~96% of rows (166,185) store the raw CMS numeric control-type code (1–13) rather than the text label — no crosswalk table ships with this export. ~1.4% (2,496) are null. Only ~3% carry the human-readable text shown in the description above.
hospital_type VARCHAR Facility type (e.g. "Acute Care Hospitals", "Critical Access Hospitals", "Psychiatric", "Long-term", "Childrens", "Rural Emergency Hospital"). Mostly missing/coded: ~55% of rows (95,044) are null, ~27% (46,206) hold a raw numeric code instead of text, leaving only ~19% with a resolved text label.
total_beds / available_beds INTEGER Licensed / staffed-and-available bed counts as filed. —
total_inpatient_days / medicare_inpatient_days / medicaid_inpatient_days BIGINT Total patient-days for the fiscal year, and the Medicare/Medicaid-attributed subsets. —
total_outpatient_visits / total_discharges BIGINT Outpatient visit count and total inpatient discharges for the fiscal year. —
total_charges / total_costs / total_revenues DOUBLE Hospital-wide gross charges, total costs, and total revenues for the fiscal year, in dollars. Charges ≠ what payers actually pay — see HPT Negotiated Rates for actual negotiated/cash prices.
medicare_charges / medicare_costs / medicaid_charges DOUBLE Charges and costs attributable specifically to Medicare and Medicaid patients. Thinly filed: medicare_costs on 17,430 and medicaid_charges on 3,163 of 173,959 rows.
medicaid_costs DOUBLE Costs attributable specifically to Medicaid patients. Present in the schema, not populated in this release. Null on all 173,959 rows. No cost report in the loaded history carries a value on the worksheet line it maps to. Use medicaid_charges (3,163 rows) if a Medicaid figure is essential, and note it is charges, not costs.
bad_debt DOUBLE Bad debt expense recognized for the fiscal year. —
charity_care_charges / uncompensated_care DOUBLE Charges written off as charity care, and total uncompensated care (charity care + bad debt, per CMS worksheet S-10 methodology). —
net_income DOUBLE Total revenues minus total costs for the fiscal year. Used to compute operating margin (net_income / total_revenues) in the source app; not pre-computed in this export.
total_assets / total_liabilities / fund_balance DOUBLE Fiscal-year-end balance sheet: total assets, total liabilities, and fund balance (assets − liabilities). —
total_salaries / total_fte DOUBLE Total salary expense and total full-time-equivalent staff count for the fiscal year. —
resident_count_inpatient DOUBLE Medical resident FTE count on inpatient rotation, for teaching hospitals. Populated on 4,621 of 173,959 rows; null for the large majority of non-teaching hospitals.
resident_count_outpatient DOUBLE Medical resident FTE count on outpatient rotation. Present in the schema, not populated in this release. Null on all 173,959 rows. No cost report in the loaded history carries a value on the outpatient rotation line; only the inpatient count above is filled.
ownership_change_flag BOOLEAN Whether CMS recorded an ownership/control change (CHOW) affecting this cost-report period. Defaults false; only a small minority are true.
ingested_at TIMESTAMP WITH TIME ZONE When this row was last (re-)ingested into the source database. Distinct from _vintage (a fixed constant) and _exported_at (this Parquet snapshot's export time) — see the README.

Known limits

Read these before you build on the numeric columns.

total_assets carries implausible outliers. 44 rows across 12 distinct CCNs report total assets above $20bn — impossible for a single hospital and inconsistent with the same row's revenue. The worst case is CCN 420004 (Medical University of South Carolina) FY2025: $85.69bn of total assets on $2.51bn of total revenues, a 34× asset-to-revenue ratio against a sector norm of roughly 1–2×. Others in the same shape include CCN 370093 (OU Medical Center) FY2024 at $85.31bn on $1.97bn, and CCN 100012 (Lee Memorial Hospital) FY2022 at $54.66bn on $1.28bn. These are as-filed values — CMS does not validate the balance-sheet worksheet, and a misplaced decimal or a whole-system balance sheet filed against one CCN survives ingestion. We ship what was filed rather than silently correcting it.

What to do: screen before aggregating. Any sum, mean or percentile of total_assets (or a ratio built on it, such as return on assets) is dominated by these rows. A practical guard is to drop rows where total_assets > 50 * total_revenues, or simply cap at $20bn; a national sum(total_assets) without a guard is wrong by tens of billions.

zip was not trustworthy before the 2026-09-11 export, and is now verified or NULL. Three separate defects were found and fixed in that export:

  1. CCN in the ZIP field — 4,584 rows. A 6-character CCN passes a 5-digit ZIP check once the leading zero is dropped, so the value geocoded to a real but wrong location (CCN 381310, Pioneer Memorial Hospital, Heppner OR shipped zip = '381310'; the true ZIP is 97836). The cause was a transposed line/column key in the loader that backfilled FY2022–FY2025 filings from the HCRIS ALPHA worksheet.
  2. Format — 49,434 rows. The cost-report header field is a ZIP+4 box, so 30,356 rows shipped as 36302- (a valid ZIP with an empty +4 and a dangling hyphen), 18,680 as 36302-1234, and 398 in other shapes (191044303, 17055-20). All now ship as the bare 5-digit 36302; the +4 is deliberately dropped so the column is one clean join key.
  3. ZIP contradicting state — 710 rows. 359 carried a ZIP the Census ZCTA reference assigns to a different state (e.g. state = 'LA' with 76901, San Angelo TX), and 351 carried a value that is not a real ZIP in that state at all (including 00000). Where the two disagree the ZIP is NULLed and the state kept — the state is corroborated by the CCN, NPI and city.

What you get now: 161,378 non-null ZIPs, of which 100% are a real 5-digit US ZIP whose state matches the state column; 12,581 NULL, of which 7,281 were blank at source. A NULL zip means we could not verify it, not the hospital has no address. The full rule and the reference file (data/reference/zcta-state-2020.csv, Census 2020 ZCTA-to-county, retrieved 2026-09-11) are documented in the dictionaries README.

If you hold an export dated before 2026-09-11: discard zip wherever it equals ccn, strip anything after the first five digits, and do not trust the remainder against state.

The crosswalk to operators is neither complete nor unique. About 30% of FY2019+ rows resolve to a parent operator at all, and the crosswalk itself holds duplicate CCNs — see the Known limits section of the Operator Crosswalk dictionary before joining.

Example queries (Snowflake)

-- 1. Financial-distress screen: hospitals with negative net income and
--    high uncompensated care, most recent fiscal year on file per CCN.
SELECT "ccn", "provider_name", "state", "fy_end_year", "total_revenues", "net_income",
       "uncompensated_care"
FROM HEALTHPARSE_DATA.HCRIS_HOSPITAL_FINANCIALS.HCRIS_HOSPITAL_FINANCIALS
WHERE "net_income" < 0
QUALIFY ROW_NUMBER() OVER (PARTITION BY "ccn" ORDER BY "fy_end" DESC) = 1
ORDER BY "uncompensated_care" DESC
LIMIT 100;

-- 2. Operating margin trend for a single hospital across all filed years.
SELECT "ccn", "provider_name", "fy_end_year",
       "total_revenues", "net_income",
       CASE WHEN "total_revenues" > 0 THEN "net_income" / "total_revenues" END AS operating_margin
FROM HEALTHPARSE_DATA.HCRIS_HOSPITAL_FINANCIALS.HCRIS_HOSPITAL_FINANCIALS
WHERE "ccn" = '340001'
ORDER BY "fy_end_year";

-- 3. State-level rollup: total beds and aggregate net income by state,
--    latest fiscal year available per CCN.
SELECT "state", count(DISTINCT "ccn") AS hospitals, sum("total_beds") AS total_beds,
       sum("net_income") AS aggregate_net_income
FROM (
  SELECT *
  FROM HEALTHPARSE_DATA.HCRIS_HOSPITAL_FINANCIALS.HCRIS_HOSPITAL_FINANCIALS
  QUALIFY ROW_NUMBER() OVER (PARTITION BY "ccn" ORDER BY "fy_end" DESC) = 1
)
GROUP BY "state"
ORDER BY hospitals DESC;