Skip to content

refactor: fix mart_patient_360 — eliminate cartesian explosion, hash SSN, add financial metrics - #1

Open
altimateanas wants to merge 1 commit into
column-level-lineage-difffrom
refactor/mart-patient-360-fix-cartesian-and-pii
Open

altimateanas wants to merge 1 commit into
column-level-lineage-difffrom
refactor/mart-patient-360-fix-cartesian-and-pii

Conversation

@altimateanas

Copy link
Copy Markdown
Owner

Summary

Major refactor of mart_patient_360 to fix critical data quality and HIPAA compliance issues.

Problems Fixed

Issue Severity What Changed
Cartesian explosion 🔴 Critical Raw 1:many joins (patients × encounters × diagnoses × medications × labs) produced millions of duplicate rows. Now pre-aggregates each domain to patient grain before joining.
Missing primary key 🔴 Critical patient_id was not in the SELECT list. Added as explicit first column.
Raw SSN exposure 🔴 HIPAA ssn was exposed as plain text. Replaced with sha2(ssn, 256) as ssn_hash.
No financial data 🟡 Gap Added stg_claims as new upstream + lifetime_charges_dollars / lifetime_paid_dollars using the cents_to_dollars macro (which existed but was never used).
Ambiguous full_name 🟡 Clarity Renamed to patient_name (from stg_patients). Added primary_provider_name (derived from stg_providers via encounter history).
Missing documentation 🟡 Gap mart_patient_360 was not listed in _marts.yml at all. Added full column-level documentation.

Column-Level Changes

Change Column Details
🟢 ADDED patient_id Primary key — was completely missing
🟢 ADDED primary_provider_name New column from stg_providers.full_name via encounter join
🟢 ADDED blood_type, insurance_id Patient demographics now included
🟢 ADDED total_encounters, first_encounter_date, last_encounter_date Aggregated encounter metrics
🟢 ADDED unique_diagnosis_count, primary_diagnosis_codes Aggregated diagnosis metrics
🟢 ADDED unique_medication_count Aggregated medication metric
🟢 ADDED total_lab_tests, abnormal_lab_count Aggregated lab metrics
🟢 ADDED lifetime_charges_dollars, lifetime_paid_dollars Financial summary from claims
🟢 ADDED patient_registered_at Renamed from created_at for clarity
🟡 RENAMED full_name → patient_name Same source (stg_patients), clearer name
🟡 CHANGED ssn → ssn_hash Source is still stg_patients.ssn, but now SHA-256 hashed
🔴 REMOVED diagnosis_code Raw per-row diagnosis code removed; replaced by aggregated unique_diagnosis_count + primary_diagnosis_codes

New Upstream Dependencies

  • stg_providers — to derive primary_provider_name
  • stg_claims — to compute financial summary

⚠️ Breaking Changes for Downstream Consumers

Any dashboard, report, or model that reads mart_patient_360 should be checked for:

  1. ssn column no longer exists — replaced by ssn_hash
  2. full_name column no longer exists — renamed to patient_name
  3. diagnosis_code column no longer exists — replaced by aggregated columns
  4. Row count will change dramatically — from cartesian explosion (millions of rows) to one row per patient (correct grain)

…ancial metrics

- Fix cartesian product: pre-aggregate encounters, diagnoses, medications,
  labs, and claims to patient grain before joining
- HIPAA compliance: replace raw ssn with sha2(ssn) as ssn_hash
- Add stg_providers + stg_claims as new upstream dependencies
- Rename full_name -> patient_name (sourced from stg_patients)
- Add primary_provider_name (now derived from stg_providers via encounters)
- Add financial columns: lifetime_charges_dollars, lifetime_paid_dollars
  using the cents_to_dollars macro
- Add patient_id as explicit primary key (was missing entirely)
- Remove raw diagnosis_code, replace with aggregated metrics
- Add schema documentation to _marts.yml (was completely missing)
@github-actions

Copy link
Copy Markdown

SQL Quality Gate Results

Checked SQL files in this PR for common anti-patterns:

  • SELECT * (prefer explicit columns)
  • Cartesian joins (missing JOIN conditions)
  • Non-sargable predicates (functions on columns in WHERE)
  • UNION without ALL (unnecessary dedup sort)
  • ORDER BY in subqueries (ignored by optimizer)
  • Missing LIMIT in analysis queries

See job logs for details.

Powered by MedFlow SQL Quality Gate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant