| | 1 | = Advanced Reports = |
| | 2 | |
| | 3 | |
| | 4 | ---- |
| | 5 | |
| | 6 | == Doctor performance analytics == |
| | 7 | |
| | 8 | This 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 | |
| | 16 | Six factors feed into one weighted performance_score: appointment completion, |
| | 17 | procedure documentation, lab result availability, and referral follow-up each |
| | 18 | contribute a percentage-based rate, while procedure volume and patient breadth |
| | 19 | contribute capped counts (so one very busy doctor can't dominate the score). Doctors |
| | 20 | are then ranked with DENSE_RANK(), so tied scores share a rank instead of skipping |
| | 21 | numbers. |
| | 22 | |
| | 23 | |
| | 24 | === SQL === |
| | 25 | |
| | 26 | {{{ |
| | 27 | WITH 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 | |
| | 34 | documented_procedure_ids AS ( |
| | 35 | SELECT DISTINCT procedure_id FROM procedure_results |
| | 36 | ), |
| | 37 | documented_test_ids AS ( |
| | 38 | SELECT DISTINCT test_id FROM lab_results |
| | 39 | ), |
| | 40 | |
| | 41 | doctor_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 | |
| | 57 | doctor_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 | |
| | 72 | doctor_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 | |
| | 87 | doctor_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 | |
| | 104 | doctor_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 | |
| | 115 | doctor_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 | |
| | 121 | doctor_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 | |
| | 152 | SELECT *, |
| | 153 | DENSE_RANK() OVER (ORDER BY performance_score DESC) AS performance_rank |
| | 154 | FROM doctor_scores |
| | 155 | ORDER BY performance_rank, last_name, first_name; |
| | 156 | }}} |
| | 157 | |
| | 158 | === Relational Algebra === |
| | 159 | |
| | 160 | {{{ |
| | 161 | Params ← {(report_start, report_end)} |
| | 162 | |
| | 163 | DocumentedProcedureIds ← π_{procedure_id} (procedure_results) |
| | 164 | DocumentedTestIds ← π_{test_id} (lab_results) |
| | 165 | |
| | 166 | DoctorAppointments ← |
| | 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 | |
| | 187 | DoctorProcedures ← |
| | 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 | |
| | 206 | DoctorLabTests ← |
| | 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 | |
| | 225 | FollowedUpReferrals ← |
| | 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 | |
| | 235 | DoctorReferrals ← |
| | 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 | |
| | 252 | DoctorPatientTouchpoints ← |
| | 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 | |
| | 268 | DoctorUniquePatients ← |
| | 269 | γ doctor_id; total_unique_patients := COUNT_DISTINCT(patient_id) |
| | 270 | (DoctorPatientTouchpoints) |
| | 271 | |
| | 272 | DoctorScores ← |
| | 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 | |
| | 308 | RankedDoctors ← |
| | 309 | rank_dense |
| | 310 | performance_rank := ORDER BY performance_score DESC |
| | 311 | (DoctorScores) |
| | 312 | |
| | 313 | Result ← |
| | 314 | τ performance_rank ASC, last_name ASC, first_name ASC |
| | 315 | (RankedDoctors) |
| | 316 | }}} |
| | 317 | |
| | 318 | ---- |
| | 319 | |
| | 320 | == Patient health risk assessment == |
| | 321 | |
| | 322 | |
| | 323 | This 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 | |
| | 333 | These combine into a `risk_score`, bucketed into `CRITICAL`/`HIGH`/`MODERATE`/`LOW`, and ranked with DENSE_RANK(). |
| | 334 | |
| | 335 | === SQL === |
| | 336 | |
| | 337 | {{{ |
| | 338 | WITH 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 | |
| | 344 | patient_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 | |
| | 351 | patient_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 | |
| | 365 | patient_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 | |
| | 395 | patient_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 | |
| | 408 | patient_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 | |
| | 419 | patient_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 | |
| | 450 | SELECT |
| | 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 |
| | 465 | FROM patient_risk_scores |
| | 466 | WHERE chronic_diagnoses_count > 0 OR allergy_count > 0 OR current_medications > 0 |
| | 467 | ORDER BY risk_rank, last_name, first_name; |
| | 468 | }}} |
| | 469 | |
| | 470 | === Relational Algebra === |
| | 471 | |
| | 472 | {{{ |
| | 473 | Params ← {(lookback_months, risk_assessment_start)} |
| | 474 | |
| | 475 | PatientRecords ← |
| | 476 | π_{patient_id, record_id} |
| | 477 | (patients p ⟕ (p.patient_id = mr.patient_id) medical_records mr) |
| | 478 | |
| | 479 | PatientChronicConditions ← |
| | 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 | |
| | 493 | PatientMedicationProfile ← |
| | 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 | |
| | 526 | FilteredAppointments ← σ (a.appointment_date ≥ p.risk_assessment_start) (appointments a × Params p) |
| | 527 | |
| | 528 | PatientActivity ← |
| | 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 | |
| | 537 | PatientReferrals ← |
| | 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 | |
| | 546 | PatientRiskScores ← |
| | 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 | |
| | 580 | RiskCategorized ← |
| | 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 | |
| | 590 | FilteredPatients ← |
| | 591 | σ (chronic_diagnoses_count > 0 ∨ allergy_count > 0 ∨ current_medications > 0) |
| | 592 | (RiskCategorized) |
| | 593 | |
| | 594 | RankedPatients ← |
| | 595 | rank_dense |
| | 596 | risk_rank := ORDER BY risk_score DESC |
| | 597 | (FilteredPatients) |
| | 598 | |
| | 599 | Result ← |
| | 600 | τ risk_rank ASC, last_name ASC, first_name ASC |
| | 601 | (RankedPatients) |
| | 602 | }}} |