Changes between Initial Version and Version 1 of AdvancedReports


Ignore:
Timestamp:
08/29/26 13:43:39 (12 days ago)
Author:
236021
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedReports

    v1 v1  
     1= Advanced Reports =
     2
     3
     4----
     5
     6== Doctor performance analytics ==
     7
     8This report identifies which doctors are performing best over a given date range (`report_start`–`report_end`), combining several independent activity streams into one weighted score:
     9
     10* Appointment volume and completion rate.
     11* Procedure volume, revenue, and how often a performed procedure has a documented result on file.
     12* Lab test volume, revenue, and how often an ordered test type has a result available.
     13* Referral volume and whether referred patients actually followed up with the receiving doctor.
     14* Breadth of care, measured as the number of distinct patients touched across procedures, lab tests, and appointments combined.
     15
     16Six factors feed into one weighted performance_score: appointment completion,
     17procedure documentation, lab result availability, and referral follow-up each
     18contribute a percentage-based rate, while procedure volume and patient breadth
     19contribute capped counts (so one very busy doctor can't dominate the score). Doctors
     20are then ranked with DENSE_RANK(), so tied scores share a rank instead of skipping
     21numbers.
     22
     23
     24=== SQL ===
     25
     26{{{
     27WITH params AS (
     28    SELECT
     29        CAST('2026-05-16' AS DATE) AS report_start,
     30        CAST('2026-08-26' AS DATE) AS report_end
     31),
     32
     33
     34documented_procedure_ids AS (
     35    SELECT DISTINCT procedure_id FROM procedure_results
     36),
     37documented_test_ids AS (
     38    SELECT DISTINCT test_id FROM lab_results
     39),
     40
     41doctor_appointments AS (
     42    SELECT
     43        d.doctor_id, d.first_name, d.last_name, d.email_address,
     44        ds.specialization_name, dept.department_name,
     45        COUNT(*) AS total_appointments,
     46        COUNT(*) FILTER (WHERE a.status = 'COMPLETED') AS completed_appointments,
     47        COUNT(*) FILTER (WHERE a.status = 'CANCELLED') AS cancelled_appointments,
     48        ROUND(100.0 * COUNT(*) FILTER (WHERE a.status = 'COMPLETED') / NULLIF(COUNT(*), 0), 2) AS appointment_completion_rate
     49    FROM doctors d
     50        JOIN appointments a ON d.doctor_id = a.doctor_id
     51        JOIN doctor_specialization ds ON d.specialization_id = ds.specialization_id
     52        JOIN departments dept ON d.department_id = dept.department_id
     53        JOIN params p ON a.appointment_date >= p.report_start AND a.appointment_date <= p.report_end
     54    GROUP BY d.doctor_id, d.first_name, d.last_name, d.email_address, ds.specialization_name, dept.department_name
     55),
     56
     57doctor_procedures AS (
     58    SELECT
     59        d.doctor_id,
     60        COUNT(*) AS procedures_performed,
     61        ROUND(AVG(proc.cost)::numeric, 2) AS avg_procedure_cost,
     62        SUM(proc.cost) AS total_procedure_revenue,
     63        ROUND(100.0 * COUNT(DISTINCT dpi.procedure_id) / NULLIF(COUNT(DISTINCT pp.procedure_id), 0), 2) AS procedure_documentation_rate
     64    FROM doctors d
     65        JOIN performed_procedures pp ON d.doctor_id = pp.doctor_id
     66        JOIN procedures proc ON pp.procedure_id = proc.procedure_id
     67        LEFT JOIN documented_procedure_ids dpi ON dpi.procedure_id = pp.procedure_id
     68        JOIN params p ON pp.procedure_date >= p.report_start AND pp.procedure_date <= p.report_end
     69    GROUP BY d.doctor_id
     70),
     71
     72doctor_lab_tests AS (
     73    SELECT
     74        d.doctor_id,
     75        COUNT(*) AS lab_tests_ordered,
     76        ROUND(AVG(lt.cost)::numeric, 2) AS avg_test_cost,
     77        SUM(lt.cost) AS total_lab_revenue,
     78        ROUND(100.0 * COUNT(DISTINCT dti.test_id) / NULLIF(COUNT(DISTINCT plt.test_id), 0), 2) AS lab_result_availability_rate
     79    FROM doctors d
     80        JOIN performed_lab_tests plt ON d.doctor_id = plt.doctor_id
     81        JOIN lab_tests lt ON plt.test_id = lt.test_id
     82        LEFT JOIN documented_test_ids dti ON dti.test_id = plt.test_id
     83        JOIN params p ON plt.test_date >= p.report_start AND plt.test_date <= p.report_end
     84    GROUP BY d.doctor_id
     85),
     86
     87doctor_referrals AS (
     88    SELECT
     89        d.doctor_id,
     90        COUNT(DISTINCT ref.referral_id) AS referrals_made,
     91        ROUND(100.0 * COUNT(DISTINCT CASE WHEN EXISTS (
     92            SELECT 1 FROM appointments fa
     93            WHERE fa.doctor_id = ref.to_doctor_id
     94              AND fa.patient_id = mr.patient_id
     95              AND fa.appointment_date > ref.referral_date
     96        ) THEN ref.referral_id END) / NULLIF(COUNT(DISTINCT ref.referral_id), 0), 2) AS referral_followup_rate
     97    FROM doctors d
     98        JOIN referrals ref ON d.doctor_id = ref.from_doctor_id
     99        JOIN medical_records mr ON ref.record_id = mr.record_id
     100        JOIN params p ON ref.referral_date >= p.report_start AND ref.referral_date <= p.report_end
     101    GROUP BY d.doctor_id
     102),
     103
     104doctor_patient_touchpoints AS (
     105    SELECT pp.doctor_id, pp.patient_id FROM performed_procedures pp
     106        JOIN params p ON pp.procedure_date >= p.report_start AND pp.procedure_date <= p.report_end
     107    UNION
     108    SELECT plt.doctor_id, plt.patient_id FROM performed_lab_tests plt
     109        JOIN params p ON plt.test_date >= p.report_start AND plt.test_date <= p.report_end
     110    UNION
     111    SELECT a.doctor_id, a.patient_id FROM appointments a
     112        JOIN params p ON a.appointment_date >= p.report_start AND a.appointment_date <= p.report_end
     113),
     114
     115doctor_unique_patients AS (
     116    SELECT doctor_id, COUNT(DISTINCT patient_id) AS total_unique_patients
     117    FROM doctor_patient_touchpoints
     118    GROUP BY doctor_id
     119),
     120
     121doctor_scores AS (
     122    SELECT
     123        da.doctor_id, da.first_name, da.last_name, da.email_address,
     124        da.specialization_name, da.department_name,
     125        da.total_appointments, da.completed_appointments, da.cancelled_appointments, da.appointment_completion_rate,
     126        COALESCE(dp.procedures_performed, 0) AS procedures_performed,
     127        COALESCE(dp.avg_procedure_cost, 0) AS avg_procedure_cost,
     128        COALESCE(dp.total_procedure_revenue, 0) AS total_procedure_revenue,
     129        COALESCE(dp.procedure_documentation_rate, 0) AS procedure_documentation_rate,
     130        COALESCE(dl.lab_tests_ordered, 0) AS lab_tests_ordered,
     131        COALESCE(dl.avg_test_cost, 0) AS avg_test_cost,
     132        COALESCE(dl.total_lab_revenue, 0) AS total_lab_revenue,
     133        COALESCE(dl.lab_result_availability_rate, 0) AS lab_result_availability_rate,
     134        COALESCE(dr.referrals_made, 0) AS referrals_made,
     135        COALESCE(dr.referral_followup_rate, 0) AS referral_followup_rate,
     136        COALESCE(dup.total_unique_patients, 0) AS total_unique_patients,
     137        ROUND(
     138            COALESCE(da.appointment_completion_rate, 0) * 0.20
     139            + COALESCE(dp.procedure_documentation_rate, 0) * 0.20
     140            + COALESCE(dl.lab_result_availability_rate, 0) * 0.15
     141            + COALESCE(dr.referral_followup_rate, 0) * 0.15
     142            + LEAST(COALESCE(dp.procedures_performed, 0), 50) * 0.30
     143            + LEAST(COALESCE(dup.total_unique_patients, 0), 100) * 0.20
     144        , 2) AS performance_score
     145    FROM doctor_appointments da
     146        LEFT JOIN doctor_procedures dp ON da.doctor_id = dp.doctor_id
     147        LEFT JOIN doctor_lab_tests dl ON da.doctor_id = dl.doctor_id
     148        LEFT JOIN doctor_referrals dr ON da.doctor_id = dr.doctor_id
     149        LEFT JOIN doctor_unique_patients dup ON da.doctor_id = dup.doctor_id
     150)
     151
     152SELECT *,
     153    DENSE_RANK() OVER (ORDER BY performance_score DESC) AS performance_rank
     154FROM doctor_scores
     155ORDER BY performance_rank, last_name, first_name;
     156}}}
     157
     158=== Relational Algebra ===
     159
     160{{{
     161Params ← {(report_start, report_end)}
     162
     163DocumentedProcedureIds ← π_{procedure_id} (procedure_results)
     164DocumentedTestIds ← π_{test_id} (lab_results)
     165
     166DoctorAppointments ←
     167γ
     168  doctor_id := d.doctor_id; first_name := d.first_name; last_name := d.last_name;
     169  email_address := d.email_address; specialization_name := ds.specialization_name;
     170  department_name := dept.department_name;
     171  total_appointments := COUNT(*);
     172  completed_appointments := COUNT(*) FILTER (a.status = 'COMPLETED');
     173  cancelled_appointments := COUNT(*) FILTER (a.status = 'CANCELLED');
     174  appointment_completion_rate := ROUND(100.0 * COUNT(*) FILTER (a.status = 'COMPLETED') / COUNT(*), 2)
     175(
     176  σ (a.appointment_date ≥ p.report_start ∧ a.appointment_date ≤ p.report_end)
     177  (
     178    (
     179      (doctors d ⨝ (d.doctor_id = a.doctor_id) appointments a)
     180      ⨝ (d.specialization_id = ds.specialization_id) doctor_specialization ds
     181    )
     182    ⨝ (d.department_id = dept.department_id) departments dept
     183    × Params p
     184  )
     185)
     186
     187DoctorProcedures ←
     188γ
     189  doctor_id := d.doctor_id;
     190  procedures_performed := COUNT(*);
     191  avg_procedure_cost := ROUND(AVG(proc.cost), 2);
     192  total_procedure_revenue := SUM(proc.cost);
     193  procedure_documentation_rate := ROUND(100.0 * COUNT_DISTINCT(dpi.procedure_id) / COUNT_DISTINCT(pp.procedure_id), 2)
     194(
     195  σ (pp.procedure_date ≥ p.report_start ∧ pp.procedure_date ≤ p.report_end)
     196  (
     197    (
     198      (doctors d ⨝ (d.doctor_id = pp.doctor_id) performed_procedures pp)
     199      ⨝ (pp.procedure_id = proc.procedure_id) procedures proc
     200    )
     201    ⟕ (pp.procedure_id = dpi.procedure_id) DocumentedProcedureIds dpi
     202    × Params p
     203  )
     204)
     205
     206DoctorLabTests ←
     207γ
     208  doctor_id := d.doctor_id;
     209  lab_tests_ordered := COUNT(*);
     210  avg_test_cost := ROUND(AVG(lt.cost), 2);
     211  total_lab_revenue := SUM(lt.cost);
     212  lab_result_availability_rate := ROUND(100.0 * COUNT_DISTINCT(dti.test_id) / COUNT_DISTINCT(plt.test_id), 2)
     213(
     214  σ (plt.test_date ≥ p.report_start ∧ plt.test_date ≤ p.report_end)
     215  (
     216    (
     217      (doctors d ⨝ (d.doctor_id = plt.doctor_id) performed_lab_tests plt)
     218      ⨝ (plt.test_id = lt.test_id) lab_tests lt
     219    )
     220    ⟕ (plt.test_id = dti.test_id) DocumentedTestIds dti
     221    × Params p
     222  )
     223)
     224
     225FollowedUpReferrals ←
     226π_{referral_id}
     227(
     228  σ (fa.doctor_id = ref.to_doctor_id ∧ fa.patient_id = mr.patient_id ∧ fa.appointment_date > ref.referral_date)
     229  (
     230    (referrals ref ⨝ (ref.record_id = mr.record_id) medical_records mr)
     231    × appointments fa
     232  )
     233)
     234
     235DoctorReferrals ←
     236γ
     237  doctor_id := d.doctor_id;
     238  referrals_made := COUNT_DISTINCT(ref.referral_id);
     239  referral_followup_rate := ROUND(100.0 * COUNT_DISTINCT(fur.referral_id) / COUNT_DISTINCT(ref.referral_id), 2)
     240(
     241  σ (ref.referral_date ≥ p.report_start ∧ ref.referral_date ≤ p.report_end)
     242  (
     243    (
     244      (doctors d ⨝ (d.doctor_id = ref.from_doctor_id) referrals ref)
     245      ⨝ (ref.record_id = mr.record_id) medical_records mr
     246    )
     247    ⟕ (ref.referral_id = fur.referral_id) FollowedUpReferrals fur
     248    × Params p
     249  )
     250)
     251
     252DoctorPatientTouchpoints ←
     253π_{doctor_id, patient_id}
     254(
     255  σ (pp.procedure_date ≥ p.report_start ∧ pp.procedure_date ≤ p.report_end) (performed_procedures pp × Params p)
     256)
     257
     258π_{doctor_id, patient_id}
     259(
     260  σ (plt.test_date ≥ p.report_start ∧ plt.test_date ≤ p.report_end) (performed_lab_tests plt × Params p)
     261)
     262
     263π_{doctor_id, patient_id}
     264(
     265  σ (a.appointment_date ≥ p.report_start ∧ a.appointment_date ≤ p.report_end) (appointments a × Params p)
     266)
     267
     268DoctorUniquePatients ←
     269γ doctor_id; total_unique_patients := COUNT_DISTINCT(patient_id)
     270(DoctorPatientTouchpoints)
     271
     272DoctorScores ←
     273π
     274  doctor_id, first_name, last_name, email_address, specialization_name, department_name,
     275  total_appointments, completed_appointments, cancelled_appointments, appointment_completion_rate,
     276  procedures_performed := COALESCE(dp.procedures_performed, 0),
     277  avg_procedure_cost := COALESCE(dp.avg_procedure_cost, 0),
     278  total_procedure_revenue := COALESCE(dp.total_procedure_revenue, 0),
     279  procedure_documentation_rate := COALESCE(dp.procedure_documentation_rate, 0),
     280  lab_tests_ordered := COALESCE(dl.lab_tests_ordered, 0),
     281  avg_test_cost := COALESCE(dl.avg_test_cost, 0),
     282  total_lab_revenue := COALESCE(dl.total_lab_revenue, 0),
     283  lab_result_availability_rate := COALESCE(dl.lab_result_availability_rate, 0),
     284  referrals_made := COALESCE(dr.referrals_made, 0),
     285  referral_followup_rate := COALESCE(dr.referral_followup_rate, 0),
     286  total_unique_patients := COALESCE(dup.total_unique_patients, 0),
     287  performance_score :=
     288    ROUND(
     289      COALESCE(appointment_completion_rate, 0) * 0.20
     290      + COALESCE(dp.procedure_documentation_rate, 0) * 0.20
     291      + COALESCE(dl.lab_result_availability_rate, 0) * 0.15
     292      + COALESCE(dr.referral_followup_rate, 0) * 0.15
     293      + LEAST(COALESCE(dp.procedures_performed, 0), 50) * 0.30
     294      + LEAST(COALESCE(dup.total_unique_patients, 0), 100) * 0.20
     295    , 2)
     296(
     297  (
     298    (
     299      (DoctorAppointments da
     300      ⟕ (da.doctor_id = dp.doctor_id) DoctorProcedures dp)
     301      ⟕ (da.doctor_id = dl.doctor_id) DoctorLabTests dl
     302    )
     303    ⟕ (da.doctor_id = dr.doctor_id) DoctorReferrals dr
     304  )
     305  ⟕ (da.doctor_id = dup.doctor_id) DoctorUniquePatients dup
     306)
     307
     308RankedDoctors ←
     309rank_dense
     310  performance_rank := ORDER BY performance_score DESC
     311(DoctorScores)
     312
     313Result ←
     314τ performance_rank ASC, last_name ASC, first_name ASC
     315(RankedDoctors)
     316}}}
     317
     318----
     319
     320== Patient health risk assessment ==
     321
     322
     323This report identifies which patients carry the highest clinical risk, for proactive outreach and care-coordination purposes, combining:
     324
     325* Chronic condition burden is the number of distinct diagnoses on file, capped at 10 in scoring so one outlier patient can't dominate the whole composite score, plus the count of severe symptoms.
     326* Allergy severity reflects the worst allergy severity level on file for the patient.
     327* A direct medication safety flag counts how many of the patient's currently prescribed medications are linked, via `allergy_prescription_restrictions`, to one of their documented allergies. This is the strongest single signal in the score, worth 10 points per conflict.
     328* Polypharmacy tier reflects how many distinct medications the patient currently has on record, bucketed into `LOW_POLYPHARMACY`, `MODERATE_POLYPHARMACY`, or `HIGH_POLYPHARMACY`.
     329* Appointment adherence covers the completion rate and days since the last appointment, within the lookback window set by the `:lookback_months` parameter.
     330* Referral burden is the number of referrals in the last 6 months.
     331* Age acts as a standard clinical risk modifier, with patients over 65 receiving additional points.
     332
     333These combine into a `risk_score`, bucketed into `CRITICAL`/`HIGH`/`MODERATE`/`LOW`, and ranked with DENSE_RANK().
     334
     335=== SQL ===
     336
     337{{{
     338WITH params AS (
     339    SELECT
     340        CAST(:lookback_months AS INTEGER) AS lookback_months,
     341        CURRENT_DATE - (CAST(:lookback_months AS INTEGER) * INTERVAL '1 month') AS risk_assessment_start
     342),
     343
     344patient_records AS (
     345    SELECT p.patient_id, mr.record_id
     346    FROM patients p
     347        LEFT JOIN medical_records mr ON mr.patient_id = p.patient_id
     348),
     349
     350
     351patient_chronic_conditions AS (
     352    SELECT
     353        p.patient_id, p.first_name, p.last_name, p.embg,
     354        EXTRACT(YEAR FROM AGE(CURRENT_DATE, p.date_of_birth))::int AS age,
     355        COUNT(DISTINCT d.diagnosis_id) AS chronic_diagnoses_count,
     356        COUNT(DISTINCT CASE WHEN UPPER(mrs.severity) = 'SEVERE' THEN mrs.symptom_id END) AS severe_symptoms_count
     357    FROM patients p
     358        LEFT JOIN diagnosis d ON d.patient_id = p.patient_id
     359        LEFT JOIN patient_records pr ON pr.patient_id = p.patient_id
     360        LEFT JOIN medical_record_symptoms mrs ON mrs.record_id = pr.record_id
     361    GROUP BY p.patient_id, p.first_name, p.last_name, p.embg, p.date_of_birth
     362),
     363
     364
     365patient_medication_profile AS (
     366    SELECT
     367        p.patient_id,
     368        COUNT(DISTINCT pmr.prescription_id) AS current_medications,
     369        CASE
     370            WHEN COUNT(DISTINCT pmr.prescription_id) >= 5 THEN 'HIGH_POLYPHARMACY'
     371            WHEN COUNT(DISTINCT pmr.prescription_id) >= 3 THEN 'MODERATE_POLYPHARMACY'
     372            ELSE 'LOW_POLYPHARMACY'
     373        END AS polypharmacy_status,
     374        COUNT(DISTINCT pa.allergy_id) AS allergy_count,
     375        CASE
     376            WHEN COUNT(DISTINCT CASE WHEN a.allergy_severity = 'CRITICAL' THEN pa.allergy_id END) > 0 THEN 'CRITICAL'
     377            WHEN COUNT(DISTINCT CASE WHEN a.allergy_severity = 'HIGH' THEN pa.allergy_id END) > 0 THEN 'HIGH'
     378            WHEN COUNT(DISTINCT pa.allergy_id) > 0 THEN 'MEDIUM'
     379            ELSE 'LOW'
     380        END AS max_allergy_severity,
     381        COUNT(DISTINCT restr.restriction_id) FILTER (WHERE pmr2.prescription_id IS NOT NULL)
     382            AS conflicting_restrictions_on_current_meds
     383    FROM patients p
     384        LEFT JOIN patient_records pr ON pr.patient_id = p.patient_id
     385        LEFT JOIN prescription_medical_records pmr ON pmr.record_id = pr.record_id
     386        LEFT JOIN patient_allergies pa ON pa.patient_id = p.patient_id
     387        LEFT JOIN allergies a ON a.allergy_id = pa.allergy_id
     388        LEFT JOIN allergy_prescription_restrictions apr ON apr.allergy_id = a.allergy_id
     389        LEFT JOIN prescription_restriction restr ON restr.restriction_id = apr.restriction_id
     390        LEFT JOIN prescription_medical_records pmr2
     391            ON pmr2.record_id = pr.record_id AND pmr2.prescription_id = restr.prescription_id
     392    GROUP BY p.patient_id
     393),
     394
     395patient_activity AS (
     396    SELECT
     397        p.patient_id,
     398        ROUND(100.0 * COUNT(a.appointment_id) FILTER (WHERE a.status = 'COMPLETED')
     399            / NULLIF(COUNT(a.appointment_id), 0), 2) AS appointment_completion_rate,
     400        CURRENT_DATE - MAX(a.appointment_date) AS days_since_last_appointment
     401    FROM patients p
     402        LEFT JOIN appointments a
     403            ON a.patient_id = p.patient_id
     404            AND a.appointment_date >= (SELECT risk_assessment_start FROM params)
     405    GROUP BY p.patient_id
     406),
     407
     408patient_referrals AS (
     409    SELECT
     410        p.patient_id,
     411        COUNT(DISTINCT CASE WHEN r.referral_date > CURRENT_DATE - INTERVAL '6 months' THEN r.referral_id END)
     412            AS referrals_last_6_months
     413    FROM patients p
     414        LEFT JOIN patient_records pr ON pr.patient_id = p.patient_id
     415        LEFT JOIN referrals r ON r.record_id = pr.record_id
     416    GROUP BY p.patient_id
     417),
     418
     419patient_risk_scores AS (
     420    SELECT
     421        pcc.patient_id, pcc.first_name, pcc.last_name, pcc.embg, pcc.age,
     422        pcc.chronic_diagnoses_count, pcc.severe_symptoms_count,
     423        COALESCE(pmp.allergy_count, 0) AS allergy_count,
     424        COALESCE(pmp.max_allergy_severity, 'LOW') AS max_allergy_severity,
     425        COALESCE(pmp.conflicting_restrictions_on_current_meds, 0) AS conflicting_restrictions_on_current_meds,
     426        COALESCE(pmp.current_medications, 0) AS current_medications,
     427        COALESCE(pmp.polypharmacy_status, 'LOW_POLYPHARMACY') AS polypharmacy_status,
     428        COALESCE(pa.appointment_completion_rate, 100) AS appointment_completion_rate,
     429        COALESCE(pa.days_since_last_appointment, 9999) AS days_since_last_appointment,
     430        COALESCE(pr.referrals_last_6_months, 0) AS referrals_last_6_months,
     431        ROUND(
     432            LEAST(COALESCE(pcc.chronic_diagnoses_count, 0), 10) * 3
     433            + COALESCE(pcc.severe_symptoms_count, 0) * 4
     434            + CASE COALESCE(pmp.max_allergy_severity, 'LOW')
     435                  WHEN 'CRITICAL' THEN 20 WHEN 'HIGH' THEN 10 WHEN 'MEDIUM' THEN 5 ELSE 0 END
     436            + CASE COALESCE(pmp.polypharmacy_status, 'LOW_POLYPHARMACY')
     437                  WHEN 'HIGH_POLYPHARMACY' THEN 15 WHEN 'MODERATE_POLYPHARMACY' THEN 8 ELSE 0 END
     438            + COALESCE(pmp.conflicting_restrictions_on_current_meds, 0) * 10
     439            + (100 - COALESCE(pa.appointment_completion_rate, 100)) * 0.2
     440            + CASE WHEN COALESCE(pa.days_since_last_appointment, 9999) > 180 THEN 10 ELSE 0 END
     441            + COALESCE(pr.referrals_last_6_months, 0) * 2
     442            + CASE WHEN pcc.age > 65 THEN 10 ELSE 0 END
     443        , 2) AS risk_score
     444    FROM patient_chronic_conditions pcc
     445        LEFT JOIN patient_medication_profile pmp ON pmp.patient_id = pcc.patient_id
     446        LEFT JOIN patient_activity pa ON pa.patient_id = pcc.patient_id
     447        LEFT JOIN patient_referrals pr ON pr.patient_id = pcc.patient_id
     448)
     449
     450SELECT
     451    patient_id, first_name, last_name, embg, age,
     452    chronic_diagnoses_count, severe_symptoms_count,
     453    allergy_count, max_allergy_severity, conflicting_restrictions_on_current_meds,
     454    current_medications, polypharmacy_status,
     455    appointment_completion_rate, days_since_last_appointment,
     456    referrals_last_6_months,
     457    risk_score,
     458    CASE
     459        WHEN risk_score > 75 THEN 'CRITICAL'
     460        WHEN risk_score > 50 THEN 'HIGH'
     461        WHEN risk_score > 25 THEN 'MODERATE'
     462        ELSE 'LOW'
     463    END AS risk_category,
     464    DENSE_RANK() OVER (ORDER BY risk_score DESC) AS risk_rank
     465FROM patient_risk_scores
     466WHERE chronic_diagnoses_count > 0 OR allergy_count > 0 OR current_medications > 0
     467ORDER BY risk_rank, last_name, first_name;
     468}}}
     469
     470=== Relational Algebra ===
     471
     472{{{
     473Params ← {(lookback_months, risk_assessment_start)}
     474
     475PatientRecords ←
     476π_{patient_id, record_id}
     477(patients p ⟕ (p.patient_id = mr.patient_id) medical_records mr)
     478
     479PatientChronicConditions ←
     480γ
     481  patient_id := p.patient_id; first_name := p.first_name; last_name := p.last_name; embg := p.embg;
     482  age := YEAR(AGE(CURRENT_DATE, p.date_of_birth));
     483  chronic_diagnoses_count := COUNT_DISTINCT(d.diagnosis_id);
     484  severe_symptoms_count := COUNT_DISTINCT(CASE WHEN UPPER(mrs.severity) = 'SEVERE' THEN mrs.symptom_id END)
     485(
     486  (
     487    (patients p ⟕ (p.patient_id = d.patient_id) diagnosis d)
     488    ⟕ (p.patient_id = pr.patient_id) PatientRecords pr
     489  )
     490  ⟕ (pr.record_id = mrs.record_id) medical_record_symptoms mrs
     491)
     492
     493PatientMedicationProfile ←
     494γ
     495  patient_id := p.patient_id;
     496  current_medications := COUNT_DISTINCT(pmr.prescription_id);
     497  polypharmacy_status :=
     498    CASE WHEN COUNT_DISTINCT(pmr.prescription_id) ≥ 5 THEN 'HIGH_POLYPHARMACY'
     499         WHEN COUNT_DISTINCT(pmr.prescription_id) ≥ 3 THEN 'MODERATE_POLYPHARMACY'
     500         ELSE 'LOW_POLYPHARMACY' END;
     501  allergy_count := COUNT_DISTINCT(pa.allergy_id);
     502  max_allergy_severity :=
     503    CASE WHEN COUNT_DISTINCT(CASE WHEN a.allergy_severity = 'CRITICAL' THEN pa.allergy_id END) > 0 THEN 'CRITICAL'
     504         WHEN COUNT_DISTINCT(CASE WHEN a.allergy_severity = 'HIGH' THEN pa.allergy_id END) > 0 THEN 'HIGH'
     505         WHEN COUNT_DISTINCT(pa.allergy_id) > 0 THEN 'MEDIUM' ELSE 'LOW' END;
     506  conflicting_restrictions_on_current_meds :=
     507    COUNT_DISTINCT(restr.restriction_id) FILTER (pmr2.prescription_id IS NOT NULL)
     508(
     509  (
     510    (
     511      (
     512        (
     513          (patients p ⟕ (p.patient_id = pr.patient_id) PatientRecords pr)
     514          ⟕ (pr.record_id = pmr.record_id) prescription_medical_records pmr
     515        )
     516        ⟕ (p.patient_id = pa.patient_id) patient_allergies pa
     517      )
     518      ⟕ (pa.allergy_id = a.allergy_id) allergies a
     519    )
     520    ⟕ (a.allergy_id = apr.allergy_id) allergy_prescription_restrictions apr
     521  )
     522  ⟕ (apr.restriction_id = restr.restriction_id) prescription_restriction restr
     523  ⟕ (pr.record_id = pmr2.record_id ∧ pmr2.prescription_id = restr.prescription_id) prescription_medical_records pmr2
     524)
     525
     526FilteredAppointments ← σ (a.appointment_date ≥ p.risk_assessment_start) (appointments a × Params p)
     527
     528PatientActivity ←
     529γ
     530  patient_id := p.patient_id;
     531  appointment_completion_rate := ROUND(100.0 * COUNT(fa.appointment_id) FILTER (fa.status = 'COMPLETED') / COUNT(fa.appointment_id), 2);
     532  days_since_last_appointment := CURRENT_DATE - MAX(fa.appointment_date)
     533(
     534  patients p ⟕ (p.patient_id = fa.patient_id) FilteredAppointments fa
     535)
     536
     537PatientReferrals ←
     538γ
     539  patient_id := p.patient_id;
     540  referrals_last_6_months := COUNT_DISTINCT(CASE WHEN r.referral_date > CURRENT_DATE - 6 MONTHS THEN r.referral_id END)
     541(
     542  (patients p ⟕ (p.patient_id = pr.patient_id) PatientRecords pr)
     543  ⟕ (pr.record_id = r.record_id) referrals r
     544)
     545
     546PatientRiskScores ←
     547π
     548  patient_id, first_name, last_name, embg, age, chronic_diagnoses_count, severe_symptoms_count,
     549  allergy_count := COALESCE(pmp.allergy_count, 0),
     550  max_allergy_severity := COALESCE(pmp.max_allergy_severity, 'LOW'),
     551  conflicting_restrictions_on_current_meds := COALESCE(pmp.conflicting_restrictions_on_current_meds, 0),
     552  current_medications := COALESCE(pmp.current_medications, 0),
     553  polypharmacy_status := COALESCE(pmp.polypharmacy_status, 'LOW_POLYPHARMACY'),
     554  appointment_completion_rate := COALESCE(pa.appointment_completion_rate, 100),
     555  days_since_last_appointment := COALESCE(pa.days_since_last_appointment, 9999),
     556  referrals_last_6_months := COALESCE(pr.referrals_last_6_months, 0),
     557  risk_score :=
     558    ROUND(
     559      LEAST(COALESCE(chronic_diagnoses_count, 0), 10) * 3
     560      + COALESCE(severe_symptoms_count, 0) * 4
     561      + CASE COALESCE(pmp.max_allergy_severity, 'LOW')
     562             WHEN 'CRITICAL' THEN 20 WHEN 'HIGH' THEN 10 WHEN 'MEDIUM' THEN 5 ELSE 0 END
     563      + CASE COALESCE(pmp.polypharmacy_status, 'LOW_POLYPHARMACY')
     564             WHEN 'HIGH_POLYPHARMACY' THEN 15 WHEN 'MODERATE_POLYPHARMACY' THEN 8 ELSE 0 END
     565      + COALESCE(pmp.conflicting_restrictions_on_current_meds, 0) * 10
     566      + (100 - COALESCE(pa.appointment_completion_rate, 100)) * 0.2
     567      + CASE WHEN COALESCE(pa.days_since_last_appointment, 9999) > 180 THEN 10 ELSE 0 END
     568      + COALESCE(pr.referrals_last_6_months, 0) * 2
     569      + CASE WHEN age > 65 THEN 10 ELSE 0 END
     570    , 2)
     571(
     572  (
     573    (PatientChronicConditions pcc
     574    ⟕ (pcc.patient_id = pmp.patient_id) PatientMedicationProfile pmp)
     575    ⟕ (pcc.patient_id = pa.patient_id) PatientActivity pa
     576  )
     577  ⟕ (pcc.patient_id = pr.patient_id) PatientReferrals pr
     578)
     579
     580RiskCategorized ←
     581π
     582  *,
     583  risk_category :=
     584    CASE WHEN risk_score > 75 THEN 'CRITICAL'
     585         WHEN risk_score > 50 THEN 'HIGH'
     586         WHEN risk_score > 25 THEN 'MODERATE'
     587         ELSE 'LOW' END
     588(PatientRiskScores)
     589
     590FilteredPatients ←
     591σ (chronic_diagnoses_count > 0 ∨ allergy_count > 0 ∨ current_medications > 0)
     592(RiskCategorized)
     593
     594RankedPatients ←
     595rank_dense
     596  risk_rank := ORDER BY risk_score DESC
     597(FilteredPatients)
     598
     599Result ←
     600τ risk_rank ASC, last_name ASC, first_name ASC
     601(RankedPatients)
     602}}}