Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions models/marts/_marts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,59 @@ models:
description: "Provider-level quality metrics"
config:
materialized: table

- name: mart_patient_360
description: >
Unified patient record aggregating demographics, encounter history,
diagnoses, medications, lab results, and financial data into a single
patient-grain table. SSN is SHA-256 hashed for HIPAA compliance.
config:
materialized: table
schema: marts_pii
meta:
contains_pii: true
owner: data-governance
compliance: HIPAA
columns:
- name: patient_id
description: "Primary key β€” unique patient medical record number"
- name: patient_name
description: "Patient full name from registration (PII)"
- name: date_of_birth
description: "Patient date of birth (PII/PHI)"
- name: blood_type
description: "Patient blood type"
- name: insurance_id
description: "Insurance policy identifier"
- name: ssn_hash
description: "SHA-256 hash of SSN β€” raw SSN is never exposed downstream"
- name: phone
description: "Patient phone number (PII)"
- name: email
description: "Patient email address (PII)"
- name: address
description: "Patient mailing address (PII)"
- name: primary_provider_name
description: "Name of the most recent attending provider, derived from stg_providers via encounter history"
- name: total_encounters
description: "Count of all encounters for this patient"
- name: first_encounter_date
description: "Date of the patient's earliest encounter"
- name: last_encounter_date
description: "Date of the patient's most recent encounter"
- name: unique_diagnosis_count
description: "Count of distinct ICD diagnosis codes across all encounters"
- name: primary_diagnosis_codes
description: "Comma-separated list of all distinct diagnosis codes"
- name: unique_medication_count
description: "Count of distinct medications prescribed across all encounters"
- name: total_lab_tests
description: "Count of all lab tests ordered for this patient"
- name: abnormal_lab_count
description: "Count of lab results flagged as abnormal"
- name: lifetime_charges_dollars
description: "Total billed amount across all claims, converted from cents to dollars"
- name: lifetime_paid_dollars
description: "Total paid amount across all claims, converted from cents to dollars"
- name: patient_registered_at
description: "Timestamp when the patient record was created"
161 changes: 132 additions & 29 deletions models/marts/mart_patient_360.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,172 @@
'owner': 'data-governance',
'compliance': 'HIPAA'
}
) }}with patients as (
) }}

with patients as (

select * from {{ ref('stg_patients') }}

)
,
),

encounters as (

select * from {{ ref('stg_encounters') }}

)
,
),

providers as (

select * from {{ ref('stg_providers') }}

),

diagnoses as (

select * from {{ ref('stg_diagnoses') }}

)
,
),

medications as (

select * from {{ ref('stg_medications') }}

)
,
),

lab_results as (

select * from {{ ref('stg_lab_results') }}

)
,
),

claims as (

select * from {{ ref('stg_claims') }}

),

-- Pre-aggregate encounters to patient grain to prevent cartesian explosion
encounter_summary as (

select
enc.patient_id,
count(*) as total_encounters,
min(enc.admission_date) as first_encounter_date,
max(enc.admission_date) as last_encounter_date,
-- Get the primary provider from the most recent encounter
max(prov.full_name) as primary_provider_name
from encounters as enc
left join providers as prov
on enc.attending_physician_id = prov.provider_id
group by enc.patient_id

),

-- Pre-aggregate diagnoses to patient grain
diagnosis_summary as (

select
enc.patient_id,
count(distinct diag.diagnosis_code) as unique_diagnosis_count,
listagg(distinct diag.diagnosis_code, ', ') as primary_diagnosis_codes
from diagnoses as diag
inner join encounters as enc
on diag.encounter_id = enc.encounter_id
group by enc.patient_id

),

-- Pre-aggregate medications to patient grain
medication_summary as (

select
enc.patient_id,
count(distinct med.medication_name) as unique_medication_count
from medications as med
inner join encounters as enc
on med.encounter_id = enc.encounter_id
group by enc.patient_id

),

-- Pre-aggregate labs to patient grain
lab_summary as (

select
patient_id,
count(*) as total_lab_tests,
sum(case when abnormal_flag = 'True' then 1 else 0 end) as abnormal_lab_count
from lab_results
group by patient_id

),

-- Pre-aggregate claims to patient grain using cents_to_dollars macro
claims_summary as (

select
patient_id,
{{ cents_to_dollars('sum(billed_cents)') }} as lifetime_charges_dollars,
{{ cents_to_dollars('sum(paid_cents)') }} as lifetime_paid_dollars
from claims
group by patient_id

),

final as (

select
-- Primary key
patients.patient_id,

-- Patient demographics
patients.full_name as patient_name,
patients.date_of_birth,
patients.blood_type,
patients.insurance_id,

-- PII columns (HIPAA: hashed for downstream safety)
sha2(patients.ssn, 256) as ssn_hash,
patients.phone,
patients.email,
patients.address,

-- Provider context (derived from encounters + providers)
enc_s.primary_provider_name,

-- Encounter metrics
coalesce(enc_s.total_encounters, 0) as total_encounters,
enc_s.first_encounter_date,
enc_s.last_encounter_date,

-- Diagnosis metrics
coalesce(dx_s.unique_diagnosis_count, 0) as unique_diagnosis_count,
dx_s.primary_diagnosis_codes,

-- Dimensions
-- Medication metrics
coalesce(med_s.unique_medication_count, 0) as unique_medication_count,

-- Lab metrics
coalesce(lab_s.total_lab_tests, 0) as total_lab_tests,
coalesce(lab_s.abnormal_lab_count, 0) as abnormal_lab_count,

-- PII columns (restricted access)
-- HIPAA: These fields require role-based access control
full_name,
ssn,
date_of_birth,
phone,
email,
address,
diagnoses.diagnosis_code
-- Financial summary
coalesce(clm_s.lifetime_charges_dollars, 0) as lifetime_charges_dollars,
coalesce(clm_s.lifetime_paid_dollars, 0) as lifetime_paid_dollars,

patients.created_at as patient_registered_at

from patients
left join encounters
on patients.patient_id = encounters.patient_id
left join diagnoses
on encounters.encounter_id = diagnoses.encounter_id
left join medications
on encounters.encounter_id = medications.encounter_id
left join lab_results
on patients.patient_id = lab_results.patient_id
left join encounter_summary as enc_s
on patients.patient_id = enc_s.patient_id
left join diagnosis_summary as dx_s
on patients.patient_id = dx_s.patient_id
left join medication_summary as med_s
on patients.patient_id = med_s.patient_id
left join lab_summary as lab_s
on patients.patient_id = lab_s.patient_id
left join claims_summary as clm_s
on patients.patient_id = clm_s.patient_id

)

Expand Down
Loading