# PBP inpatient psychiatric (cleaned view)

`medicare_semantic.vw_pbp_inpatient_psychiatric` · Medicare Advantage, Part D, Medicaid · status live

Cleaned source-faithful PBP inpatient psychiatric rows: era-normalized, CMS codes decoded, with offered_status/numeric_amount_observability/null_amount_reason/annualization_policy/combined_limit_policy/confidence_tier. The agent reasoning s

**Grain.** One row per MA plan-segment per quarterly PBP snapshot — i.e., one row per (contract_id, plan_id, segment_id, report_year, quarter). Verified unique: 193,172 distinct combinations = 193,172 rows, 0 duplicates, max 1 row per key. The same plan recurs across multiple quarterly snapshots and across years, so the table is a longitudinal stack of snapshots, NOT a current-state table. There are 23,191 distinct plan-segments and 1,838 distinct contracts across 2007-2026.

**How to use it.** Compare what MA plans charge members for an inpatient psychiatric stay in the latest year. Example: get the current admission copay per plan — SELECT contract_id, plan_id, segment_id, copay_amount, tier_1_day_interval_1_copay, tier_1_day_count_per_interval, auth_required FROM medicare_semantic.vw_pbp_inpatient_psychiatric WHERE report_year = 2026 AND quarter = (SELECT max(quarter) FROM medicare_semantic.vw_pbp_inpatient_psychiatric WHERE report_year = 2026). To dedup a plan to its single most-recent snapshot across years, take the row with max (report_year, quarter) per (contract_id, plan_id, segment_id). Use copay_amount/tier_1_day_admission_copay IS NOT NULL to restrict to plans with a captured numeric copay.

**Traps.**
- Snapshot stacking, no is_current flag: the same plan appears in multiple quarterly snapshots — 17,470 plan-years appear in ALL 4 quarters, and many span 2-3. A plan-level query that does not pin (report_year, quarter) will multi-count plans (e.g. 2023 has 31,005 rows for only 7,766 plans). For current state, pick the latest (report_year, quarter) per (contract_id, plan_id, segment_id) — that yields exactly 23,191 rows, one per plan-segment. report_year (NOT quarter) is the benefit-year axis; the profiler mislabeled 'quarter' as the time column.
- cost_share_string is malformed: rows like '$900.0 copay + 900.0%' duplicate the copay dollar figure as a fake coinsurance percent (900% is impossible). The structured columns are correct (has_coinsurance=FALSE, coinsurance_pct=NULL there); never parse the '+ N.N%' suffix as real coinsurance. coinsurance_pct is 100% NULL table-wide, so no usable coinsurance value exists even when has_coinsurance=TRUE (flag-only).
- Many governance/limit columns are dead in this view: coinsurance_pct, limit_text, limit_quantity, limit_unit, benefit_amount and all benefit_amount_* are 100% NULL; normalization_status/basis, aggregation_policy are 100% NULL; and network_type ('in_network'), max_oop_applies (true), offered_status ('offered'), numeric_amount_observability ('offered_without_numeric_amounts'), null_amount_reason, annualization_policy, combined_limit_policy, consumer_document_reconciliation_status ('not_checked'), confidence_tier ('source_faithful'), benefit_category, psych_tier_axis ('tier_1'), source_pbp_section/silver_table/lmi_authorities are all CONSTANT. Don't filter or pivot on these expecting variation.
- numeric_amount_observability='offered_without_numeric_amounts' is misleading: it is constant and refers to the generic benefit_amount columns, yet ~56% of rows carry real dollars in copay_amount/tier_1_day_admission_copay. Use copay_amount/tier_1_* IS NOT NULL (109,095 rows) to find plans with a captured numeric copay — not this flag. Likewise has_copay=TRUE does not imply copay_amount is populated (26,615 such rows are NULL; 13,284 have has_copay itself NULL).
- copay_amount is a duplicate of tier_1_day_admission_copay (equal in 100% of non-null cases) — they are the SAME number, not two independent cost components. The richer per-day structure lives in tier_1_day_count_per_interval + tier_1_day_interval_1_copay/interval_2_copay (e.g. ~$292/day for the first interval then $0). NULLs in auth_required (~29%), referral_required, cost_on_discharge_day (~56%), and hospital_benefit_period_code (~37%) mean 'not captured / unknown', NOT false — and NULL hospital_benefit_period_code correlates with the no-numeric-copay rows. version is pre-deduped (one per grain key); ignore it as a selector. This view is the in-network, tier-1 psych slice only — no out-of-network and no higher psych tiers.

| column | type | meaning |
|---|---|---|
| contract_id | string | CMS MA contract ID (e.g. H0028). 1,838 distinct. Part of grain key. |
| plan_id | string | Plan ID within the contract (e.g. 001, 013), zero-padded string. 656 distinct values. Part of grain key. NOT unique alone. |
| segment_id | string | PBP plan segment (geographic/benefit subdivision of a plan), string. '0' for ~92% of rows (single-segment plans); 1-7+ exist (26 distinct) for segmented plans. Part of grain key. |
| version | double | CMS PBP file release version for that plan-quarter (double, 1-27). The view has ALREADY deduped to exactly one version per grain key (max 1 version/key, 0 multi-version keys), so you do not need to filter it — but it is not a meaningful selector either. |
| report_year | double | PBP contract/benefit year (double, 2007-2026). THIS is the real year axis (the profiler mislabeled 'quarter' as the time column). Part of grain key. |
| quarter | double | Quarterly CMS PBP release snapshot within the year (1.0-4.0). Early years (2007-2017), 2021, 2025, 2026 carry only Q1; 2018-2020 and 2022-2024 carry multiple quarterly snapshots. Part of grain key and the snapshot dimension — see gotchas. |
| benefit_category | string | Constant = 'inpatient_psychiatric' for every row (this view is pre-filtered to that benefit). Not a discriminator. |
| cost_share_string | string | Human-readable cost-share summary, e.g. '$0 copay' (90,592 rows) or '$900.0 copay + 900.0%'. 313 distinct, NULL for ~44% (offered-without-numeric rows). WARNING: the '+ N.N%' suffix is a formatting BUG — it echoes the copay dollar figure as a bogus coinsurance percent (900% is nonsensical); do not parse it as coinsurance. |
| copay_amount | double | Flat/admission copay in dollars (0-2,545, median $0, 313 distinct). Non-null for 109,095 rows (~56%); the rest are NULL (numeric not captured). EXACTLY equals tier_1_day_admission_copay in 100% of non-null cases (it is a copy of it). |
| coinsurance_pct | double | Coinsurance percentage — 100% NULL across the entire table (0 non-null). The model does not populate it here (and correctly ignores the bogus % in cost_share_string). Treat as unavailable for this benefit. |
| limit_text | string | Free-text benefit limit — 100% NULL in this view. Unused. |
| auth_required | boolean | Boolean: prior authorization required for the inpatient psych stay. TRUE 122,762; NULL 56,687 (~29%, not captured); remainder false. NULL means unknown, not false. |
| referral_required | boolean | Boolean: referral required. TRUE 37,617; NULL 17,004; remainder false. NULL = unknown. |
| network_type | varchar(10) | varchar — CONSTANT 'in_network' for all 193,172 rows. This view contains NO out-of-network cost-share. Big scope limit. |
| max_oop_applies | boolean | Boolean: benefit counts toward the plan MOOP. TRUE for 100% of rows (constant, never null). Not a discriminator. |
| limit_quantity | double | Numeric benefit limit quantity — 100% NULL in this view. Unused. |
| limit_unit | string | Unit for the limit — 100% NULL. Unused. |
| limit_period_code | string | Code for the limit period — effectively NULL/unused here (appears as a candidate-key padder in the profiler but carries no value). |
| limit_period_label | string | Label for limit period — NULL/unused. |
| limit_quantity_per_year | double | Annualized limit quantity — NULL/unused in this view. |
| benefit_amount | double | Generic benefit dollar amount — 100% NULL in this view (psych cost-share lives in the tier_1_* and copay_amount columns, not here). |
| benefit_amount_kind | string | Kind of benefit_amount — 100% NULL. Unused. |
| benefit_amount_period_code | string | Period code for benefit_amount — NULL/unused (profiler key padder). |
| benefit_amount_period_label | string | Period label — NULL/unused. |
| benefit_amount_annualized | double | Annualized benefit_amount — NULL/unused. |
| benefit_amount_pmpm | double | Per-member-per-month benefit_amount — NULL/unused. |
| normalization_status | string | Governance field — 100% NULL in this view. Carried from generic PBP schema, unpopulated here. |
| normalization_basis | string | Governance field — 100% NULL. Unused. |
| aggregation_policy | string | Governance field — 100% NULL. Unused. |
| offered_status | varchar(15) | varchar — CONSTANT 'offered' for all rows (every row is a plan that offers the benefit). Not a discriminator. |
| numeric_amount_observability | varchar(31) | varchar — CONSTANT 'offered_without_numeric_amounts' for ALL rows. Misleading: it refers to the generic benefit_amount/copay_amount being absent, yet ~56% of rows DO carry real dollars in tier_1_day_admission_copay/copay_amount. Do not use this flag to decide whether a numeric copay exists. |
| null_amount_reason | varchar(30) | varchar — CONSTANT 'unknown_requires_crosswalk' for all rows. A generic default, not a per-row diagnosis. |
| annualization_policy | varchar(17) | varchar — CONSTANT 'not_numeric' for all rows. Not a discriminator. |
| combined_limit_policy | varchar(29) | varchar — CONSTANT 'none_detected' for all rows. Not a discriminator. |
| consumer_document_reconciliation_status | varchar(11) | varchar — CONSTANT 'not_checked' for all rows (no consumer-doc/EOC reconciliation has been run on this benefit). Not a discriminator. |
| confidence_tier | varchar(23) | varchar — CONSTANT 'source_faithful' for all rows (values are faithfully copied from the PBP source). Not a discriminator. |
| additional_days_amount | double |  |
| additional_days_benefit_type_code | string |  |
| additional_days_benefit_type_label | string |  |
| additional_days_coinsurance_interval1_begin_day | double |  |
| additional_days_coinsurance_interval1_end_day | double |  |
| additional_days_coinsurance_interval1_pct | double |  |
| additional_days_coinsurance_interval2_begin_day | double |  |
| additional_days_coinsurance_interval2_end_day | double |  |
| additional_days_coinsurance_interval2_pct | double |  |
| additional_days_coinsurance_interval_count | string |  |
| additional_days_copay_amount | double |  |
| additional_days_copay_interval1_amount | double |  |
| additional_days_copay_interval1_begin_day | double |  |
| additional_days_copay_interval1_end_day | double |  |
| additional_days_copay_interval2_amount | double |  |
| additional_days_copay_interval2_begin_day | double |  |
| additional_days_copay_interval2_end_day | double |  |
| additional_days_copay_interval_count | string |  |
| additional_days_cost_share_basis | string |  |
| additional_days_cost_share_lowest_tier | string |  |
| additional_days_cost_share_string | string |  |
| additional_days_cost_share_tier_count | string |  |
| additional_days_cost_varies_by_tier | boolean |  |
| additional_days_limit_code | string |  |
| additional_days_offered | boolean |  |
| additional_days_unlimited | boolean |  |
| benefit_layer | varchar(38) |  |
| benefit_period_other_text | string |  |
| coinsurance_structure_same_as_medicare_covered | boolean |  |
| copay_amount_max | double |  |
| copay_amount_max_resolved | double |  |
| copay_amount_min | double |  |
| copay_amount_min_resolved | double |  |
| copay_structure_same_as_medicare_covered | boolean |  |
| cost_on_discharge_day | boolean | Boolean: whether a copay applies on the discharge day. FALSE 82,899, TRUE 2,214, NULL 108,059 (~56%, not captured). NULL = unknown. |
| cost_share_basis | string |  |
| cost_share_lowest_tier | string |  |
| cost_share_tier_count | string |  |
| cost_varies_by_tier | boolean | Boolean: cost varies across a tier axis. TRUE for only 241 rows; mostly false. Combined with psych_tier_axis always = tier_1, multi-tier psych structures are essentially absent in this view. |
| deductible_amount | double |  |
| has_coinsurance | boolean | Boolean flag that coinsurance applies. TRUE for 38,002 rows — but coinsurance_pct is 100% NULL, so the flag exists with NO accompanying percentage value. Flag-only signal. |
| has_copay | boolean | Boolean flag that a copay applies. TRUE 135,708. NOTE: 26,615 rows have has_copay=TRUE but copay_amount IS NULL (copay exists but dollar not captured / sits in interval copays), and 13,284 rows have has_copay = NULL. Do not equate has_copay=TRUE with copay_amount being populated. |
| has_deductible | boolean | Boolean: a deductible applies. TRUE for only 1,257 rows; overwhelmingly false. Rare for this benefit. |
| has_max_enrollee_oop | boolean |  |
| hospital_benefit_period_code | string | PBP benefit-period structure code (string '1'-'4', plus NULL for 70,737 rows ~37%). '3' is most common (84,346). Does NOT split the grain (one value per plan-snapshot). NULL strongly correlates with the no-numeric-copay rows (only 7,899 of 70,737 NULL-HBPC rows have a copay). |
| hospital_benefit_period_label | string |  |
| inpatient_psychiatric_in_package_category_list | boolean |  |
| inpatient_psychiatric_package_id | string |  |
| inpatient_psychiatric_package_match | string |  |
| inpatient_psychiatric_package_name | string |  |
| inpatient_psychiatric_package_type_code | string |  |
| inpatient_psychiatric_package_type_label | string |  |
| inpatient_psychiatric_targeted_file | string |  |
| inpatient_psychiatric_targeting | varchar(36) |  |
| layer_benefit_type_code | string |  |
| layer_benefit_type_label | string |  |
| lifetime_reserve_day_copay_resolved | double |  |
| max_enrollee_oop_amount | double |  |
| max_enrollee_oop_period_code | string |  |
| original_medicare_cost_share_charged | boolean |  |
| part_a_deductible_amount_resolved | double |  |
| psych_tier_axis | varchar(39) | varchar — CONSTANT 'tier_1' for 100% of rows. This view only materializes the tier-1 psych slice; higher psych tiers are not represented here, which is why all tier_2+ columns are absent. |
| tier1_coinsurance_interval1_begin_day | double |  |
| tier1_coinsurance_interval1_end_day | double |  |
| tier1_coinsurance_interval1_pct | double |  |
| tier1_coinsurance_interval2_begin_day | double |  |
| tier1_coinsurance_interval2_end_day | double |  |
| tier1_coinsurance_interval2_pct | double |  |
| tier1_coinsurance_interval_count | string |  |
| tier1_copay_interval1_amount | double |  |
| tier1_copay_interval1_amount_resolved | double |  |
| tier1_copay_interval1_begin_day | double |  |
| tier1_copay_interval1_end_day | double |  |
| tier1_copay_interval2_amount | double |  |
| tier1_copay_interval2_amount_resolved | double |  |
| tier1_copay_interval2_begin_day | double |  |
| tier1_copay_interval2_end_day | double |  |
| tier1_copay_interval3_amount | double |  |
| tier1_copay_interval3_begin_day | double |  |
| tier1_copay_interval3_end_day | double |  |
| tier1_copay_per_stay_amount | double |  |
| tier1_lifetime_reserve_coinsurance_interval1_begin_day | double |  |
| tier1_lifetime_reserve_coinsurance_interval1_end_day | double |  |
| tier1_lifetime_reserve_coinsurance_interval1_pct | double |  |
| tier1_lifetime_reserve_coinsurance_interval2_begin_day | double |  |
| tier1_lifetime_reserve_coinsurance_interval2_end_day | double |  |
| tier1_lifetime_reserve_coinsurance_interval2_pct | double |  |
| tier1_lifetime_reserve_coinsurance_interval_count | string |  |
| tier1_lifetime_reserve_days_interval_count | string |  |
| tier1_lifetime_reserve_interval1_amount | double |  |
| tier1_lifetime_reserve_interval1_begin_day | double |  |
| tier1_lifetime_reserve_interval1_end_day | double |  |
| tier1_lifetime_reserve_interval2_amount | double |  |
| tier1_lifetime_reserve_interval2_begin_day | double |  |
| tier1_lifetime_reserve_interval2_end_day | double |  |
| tier2_charges_medicare_defined_cost_share | boolean |  |
| tier2_copay_amount_max | double |  |
| tier2_copay_interval_count | string |  |
| tier2_copay_per_stay_amount | double |  |
| tier2_lifetime_reserve_days_interval_count | string |  |
| tier2_lifetime_reserve_interval1_amount | double |  |
| tier2_lifetime_reserve_interval1_begin_day | double |  |
| tier2_lifetime_reserve_interval1_end_day | double |  |
| tier2_lifetime_reserve_interval2_amount | double |  |
| tier2_lifetime_reserve_interval2_begin_day | double |  |
| tier2_lifetime_reserve_interval2_end_day | double |  |
| tier3_charges_medicare_defined_cost_share | boolean |  |
| tier3_copay_interval_count | string |  |
| tier3_copay_per_stay_amount | double |  |
| tier3_lifetime_reserve_days_interval_count | string |  |
| tier_1_consecutive_day_count | string | String count of consecutive days the first cost-share interval applies (e.g. '1','2','3'). NULL ~44%. Part of the per-day cost structure. |
| tier_1_day_admission_copay | double | Dollar copay at admission for tier 1 (0-2,545). Non-null 109,095. Identical to copay_amount. The flat admission copay. |
| tier_1_day_count_per_interval | string | String defining how many day-intervals the copay schedule has (e.g. '1' = flat admission only with no per-day intervals; '3' = a multi-interval schedule with interval_1 and interval_2 copays). Drives whether the interval copay columns are populated. |
| tier_1_day_interval_1_begin_day | double |  |
| tier_1_day_interval_1_copay | double | Per-day copay for the first day-interval (e.g. ~$292/day median when per_interval='3'). Non-null 87,312. Encodes 'pay $X/day for the first N days'. |
| tier_1_day_interval_1_end_day | double |  |
| tier_1_day_interval_2_begin_day | double |  |
| tier_1_day_interval_2_copay | double | Per-day copay for the second day-interval (median $0 — i.e. $0/day after the first interval in the common case). Non-null 86,845. Encodes the step-down after the initial copay days. |
| tier_1_day_interval_2_end_day | double |  |
| tier_1_day_interval_3_begin_day | double |  |
| tier_1_day_interval_3_copay | double |  |
| tier_1_day_interval_3_end_day | double |  |
| tier_2_day_interval_1_begin_day | double |  |
| tier_2_day_interval_1_copay | double |  |
| tier_2_day_interval_1_end_day | double |  |
| tier_2_day_interval_2_begin_day | double |  |
| tier_2_day_interval_2_copay | double |  |
| tier_2_day_interval_2_end_day | double |  |
| tier_2_day_interval_3_begin_day | double |  |
| tier_2_day_interval_3_copay | double |  |
| tier_2_day_interval_3_end_day | double |  |
| total_covered_stay_days | double |  |
| source_pbp_section | varchar(3) | varchar — CONSTANT 'B1B' (PBP Section B1B = Inpatient Hospital - Psychiatric). Provenance, not a discriminator. |
| source_silver_table | string | varchar — CONSTANT 'medicare_silver.pbp_section_b1b_inpat_hosp_psych'. The upstream silver table this view is built from. Provenance. |
| lmi_authorities | string | String — CONSTANT pointer URL to the CY2026 PBP Service Category Descriptions PDF (LMI MA Benefits Mailbox). Documentation reference for the benefit definition; same for every row. |
| source_url | string | CMS source zip URL for the snapshot (e.g. https://www.cms.gov/files/zip/pbp-benefits-2022-updated-07012022.zip). 34 distinct = one per snapshot (year+quarter). Provenance for the specific PBP release. |
| sha256_content_hash | string | SHA-256 content hash of the source file. 34 distinct (one per snapshot zip), mirroring source_url. Integrity/provenance. |

Tools that read it: get_pbp_benefit

Query it: `query_substrate` with `SELECT ... FROM medicare_semantic.vw_pbp_inpatient_psychiatric WHERE ... LIMIT 100`; read `describe_data_source("medicare_semantic.vw_pbp_inpatient_psychiatric")` first.
