| 1 | MedicalSystem Views
|
|---|
| 2 |
|
|---|
| 3 | CREATE OR REPLACE VIEW v_patient_full_profile AS
|
|---|
| 4 | SELECT
|
|---|
| 5 | p.patient_id,
|
|---|
| 6 | p.first_name || ' ' || p.last_name AS full_name,
|
|---|
| 7 | p.date_of_birth,
|
|---|
| 8 | DATE_PART('year', AGE(p.date_of_birth))::INT AS age,
|
|---|
| 9 | p.gender,
|
|---|
| 10 | p.phone,
|
|---|
| 11 | p.email,
|
|---|
| 12 | p.address,
|
|---|
| 13 | la.appointment_date AS last_appointment_date,
|
|---|
| 14 | la.status AS last_appointment_status,
|
|---|
| 15 | la.appointment_type,
|
|---|
| 16 | d.first_name || ' ' || d.last_name AS last_doctor,
|
|---|
| 17 | sp.spec_name AS specialization,
|
|---|
| 18 | pd.diagnosis_name AS active_primary_diagnosis,
|
|---|
| 19 | icd.code AS icd_code,
|
|---|
| 20 | pd.date_from AS diagnosis_since,
|
|---|
| 21 | (SELECT COUNT(*) FROM Prescription pr
|
|---|
| 22 | WHERE pr.patient_id = p.patient_id) AS total_prescriptions,
|
|---|
| 23 | (SELECT COUNT(*) FROM Appointment a2
|
|---|
| 24 | WHERE a2.patient_id = p.patient_id) AS total_appointments
|
|---|
| 25 | FROM Patient p
|
|---|
| 26 | LEFT JOIN LATERAL (
|
|---|
| 27 | SELECT * FROM Appointment a
|
|---|
| 28 | WHERE a.patient_id = p.patient_id
|
|---|
| 29 | ORDER BY a.appointment_date DESC
|
|---|
| 30 | LIMIT 1
|
|---|
| 31 | ) la ON TRUE
|
|---|
| 32 | LEFT JOIN Doctor d ON d.doctor_id = la.doctor_id
|
|---|
| 33 | LEFT JOIN Specialization sp ON sp.spec_id = d.spec_id
|
|---|
| 34 | LEFT JOIN LATERAL (
|
|---|
| 35 | SELECT pd2.*
|
|---|
| 36 | FROM Patient_diagnosis pd2
|
|---|
| 37 | WHERE pd2.patient_id = p.patient_id
|
|---|
| 38 | AND pd2.is_primary = TRUE
|
|---|
| 39 | AND (pd2.date_to IS NULL OR pd2.date_to >= CURRENT_DATE)
|
|---|
| 40 | ORDER BY pd2.date_from DESC
|
|---|
| 41 | LIMIT 1
|
|---|
| 42 | ) pd ON TRUE
|
|---|
| 43 | LEFT JOIN ICD icd ON icd.icd_id = pd.icd_id;
|
|---|
| 44 |
|
|---|
| 45 | CREATE OR REPLACE VIEW v_doctor_workload AS
|
|---|
| 46 | SELECT
|
|---|
| 47 | d.doctor_id,
|
|---|
| 48 | d.first_name || ' ' || d.last_name AS full_name,
|
|---|
| 49 | d.email,
|
|---|
| 50 | sp.spec_name AS specialization,
|
|---|
| 51 | dep.department_name,
|
|---|
| 52 | dd.employment_type,
|
|---|
| 53 | COUNT(a.appointment_id) AS total_appointments,
|
|---|
| 54 | COUNT(CASE WHEN a.status = 'COMPLETED' THEN 1 END) AS completed,
|
|---|
| 55 | COUNT(CASE WHEN a.status = 'CANCELLED' THEN 1 END) AS cancelled,
|
|---|
| 56 | COUNT(CASE WHEN a.status = 'NO_SHOW' THEN 1 END) AS no_shows,
|
|---|
| 57 | COUNT(CASE WHEN a.status = 'SCHEDULED'
|
|---|
| 58 | AND a.appointment_date >= CURRENT_DATE
|
|---|
| 59 | THEN 1 END) AS upcoming,
|
|---|
| 60 | ROUND(
|
|---|
| 61 | 100.0 * COUNT(CASE WHEN a.status = 'COMPLETED' THEN 1 END)
|
|---|
| 62 | / NULLIF(COUNT(a.appointment_id), 0), 1
|
|---|
| 63 | ) AS completion_rate_pct,
|
|---|
| 64 | COUNT(DISTINCT a.patient_id) AS unique_patients,
|
|---|
| 65 | COUNT(DISTINCT pr.presc_id) AS prescriptions_issued,
|
|---|
| 66 | COUNT(DISTINCT me.exam_id) AS exams_conducted
|
|---|
| 67 | FROM Doctor d
|
|---|
| 68 | LEFT JOIN Specialization sp ON sp.spec_id = d.spec_id
|
|---|
| 69 | LEFT JOIN LATERAL (
|
|---|
| 70 | SELECT doc_dep.employment_type, doc_dep.department_id
|
|---|
| 71 | FROM Doctor_department doc_dep
|
|---|
| 72 | WHERE doc_dep.doctor_id = d.doctor_id
|
|---|
| 73 | AND doc_dep.date_to IS NULL
|
|---|
| 74 | ORDER BY doc_dep.date_from DESC
|
|---|
| 75 | LIMIT 1
|
|---|
| 76 | ) dd ON TRUE
|
|---|
| 77 | LEFT JOIN Department dep ON dep.department_id = dd.department_id
|
|---|
| 78 | LEFT JOIN Appointment a ON a.doctor_id = d.doctor_id
|
|---|
| 79 | LEFT JOIN Prescription pr ON pr.doctor_id = d.doctor_id
|
|---|
| 80 | LEFT JOIN Medical_examination me ON me.doctor_id = d.doctor_id
|
|---|
| 81 | GROUP BY d.doctor_id, d.first_name, d.last_name, d.email,
|
|---|
| 82 | sp.spec_name, dep.department_name, dd.employment_type;
|
|---|
| 83 |
|
|---|
| 84 | CREATE OR REPLACE VIEW v_pharmacy_inventory_sales AS
|
|---|
| 85 | SELECT
|
|---|
| 86 | ph.pharmacy_id,
|
|---|
| 87 | ph.name AS pharmacy_name,
|
|---|
| 88 | ph.address,
|
|---|
| 89 | COUNT(DISTINCT i.inventory_id) AS products_stocked,
|
|---|
| 90 | SUM(i.quantity) AS total_units_in_stock,
|
|---|
| 91 | COUNT(CASE WHEN i.quantity < 20 THEN 1 END) AS low_stock_alerts,
|
|---|
| 92 | COUNT(DISTINCT ps.sale_id) AS total_sales,
|
|---|
| 93 | COUNT(DISTINCT ps.patient_id) AS unique_customers,
|
|---|
| 94 | COALESCE(SUM(ps.total_amount), 0) AS total_revenue,
|
|---|
| 95 | ROUND(COALESCE(AVG(ps.total_amount), 0)::NUMERIC, 2) AS avg_sale_value,
|
|---|
| 96 | COUNT(CASE WHEN ps.sale_date >= CURRENT_DATE - INTERVAL '30 days'
|
|---|
| 97 | THEN 1 END) AS sales_last_30_days,
|
|---|
| 98 | COALESCE(SUM(CASE WHEN ps.sale_date >= CURRENT_DATE - INTERVAL '30 days'
|
|---|
| 99 | THEN ps.total_amount END), 0) AS revenue_last_30_days,
|
|---|
| 100 | MAX(ps.sale_date) AS last_sale_date
|
|---|
| 101 | FROM Pharmacy ph
|
|---|
| 102 | LEFT JOIN Inventory i ON i.pharmacy_id = ph.pharmacy_id
|
|---|
| 103 | LEFT JOIN Pharmacy_sale ps ON ps.pharmacy_id = ph.pharmacy_id
|
|---|
| 104 | GROUP BY ph.pharmacy_id, ph.name, ph.address;
|
|---|
| 105 |
|
|---|
| 106 | CREATE OR REPLACE VIEW v_appointment_daily_stats AS
|
|---|
| 107 | SELECT
|
|---|
| 108 | a.appointment_date,
|
|---|
| 109 | COUNT(*) AS total_appointments,
|
|---|
| 110 | COUNT(CASE WHEN a.status = 'COMPLETED' THEN 1 END) AS completed,
|
|---|
| 111 | COUNT(CASE WHEN a.status = 'CANCELLED' THEN 1 END) AS cancelled,
|
|---|
| 112 | COUNT(CASE WHEN a.status = 'NO_SHOW' THEN 1 END) AS no_shows,
|
|---|
| 113 | COUNT(CASE WHEN a.status = 'SCHEDULED' THEN 1 END) AS scheduled,
|
|---|
| 114 | COUNT(CASE WHEN a.status = 'IN_PROGRESS' THEN 1 END) AS in_progress,
|
|---|
| 115 | COUNT(CASE WHEN a.appointment_type = 'EMERGENCY' THEN 1 END) AS emergencies,
|
|---|
| 116 | COUNT(CASE WHEN a.priority_level = 'URGENT' THEN 1 END) AS urgent,
|
|---|
| 117 | COUNT(DISTINCT a.doctor_id) AS doctors_active,
|
|---|
| 118 | COUNT(DISTINCT a.patient_id) AS unique_patients,
|
|---|
| 119 | COUNT(CASE WHEN a.prescription_value = TRUE THEN 1 END) AS with_prescription,
|
|---|
| 120 | ROUND(
|
|---|
| 121 | 100.0 * COUNT(CASE WHEN a.status = 'COMPLETED' THEN 1 END)
|
|---|
| 122 | / NULLIF(COUNT(*), 0), 1
|
|---|
| 123 | ) AS completion_rate_pct
|
|---|
| 124 | FROM Appointment a
|
|---|
| 125 | GROUP BY a.appointment_date;
|
|---|
| 126 |
|
|---|
| 127 | CREATE OR REPLACE VIEW v_patient_diagnosis_history AS
|
|---|
| 128 | SELECT
|
|---|
| 129 | pd.patient_diagnosis_id,
|
|---|
| 130 | pd.patient_id,
|
|---|
| 131 | p.first_name || ' ' || p.last_name AS patient_name,
|
|---|
| 132 | d.first_name || ' ' || d.last_name AS diagnosing_doctor,
|
|---|
| 133 | sp.spec_name AS doctor_specialization,
|
|---|
| 134 | icd.code AS icd_code,
|
|---|
| 135 | icd.description AS icd_description,
|
|---|
| 136 | pd.diagnosis_name,
|
|---|
| 137 | pd.is_primary,
|
|---|
| 138 | pd.date_from,
|
|---|
| 139 | pd.date_to,
|
|---|
| 140 | CASE WHEN pd.date_to IS NULL OR pd.date_to >= CURRENT_DATE
|
|---|
| 141 | THEN 'ACTIVE' ELSE 'RESOLVED'
|
|---|
| 142 | END AS diagnosis_status,
|
|---|
| 143 | (COALESCE(pd.date_to, CURRENT_DATE) - pd.date_from)::INT AS days_active,
|
|---|
| 144 | me.exam_date,
|
|---|
| 145 | a.appointment_type
|
|---|
| 146 | FROM Patient_diagnosis pd
|
|---|
| 147 | JOIN Patient p ON p.patient_id = pd.patient_id
|
|---|
| 148 | JOIN Doctor d ON d.doctor_id = pd.doctor_id
|
|---|
| 149 | JOIN Specialization sp ON sp.spec_id = d.spec_id
|
|---|
| 150 | JOIN ICD icd ON icd.icd_id = pd.icd_id
|
|---|
| 151 | JOIN Medical_examination me ON me.exam_id = pd.exam_id
|
|---|
| 152 | JOIN Appointment a ON a.appointment_id = me.appointment_id;
|
|---|
| 153 |
|
|---|
| 154 | CREATE OR REPLACE VIEW v_lab_test_overview AS
|
|---|
| 155 | SELECT
|
|---|
| 156 | lt.lab_id,
|
|---|
| 157 | lt.test_name,
|
|---|
| 158 | lt.status AS test_status,
|
|---|
| 159 | lt.result,
|
|---|
| 160 | me.exam_date,
|
|---|
| 161 | p.patient_id,
|
|---|
| 162 | p.first_name || ' ' || p.last_name AS patient_name,
|
|---|
| 163 | p.date_of_birth,
|
|---|
| 164 | DATE_PART('year', AGE(p.date_of_birth))::INT AS patient_age,
|
|---|
| 165 | d.first_name || ' ' || d.last_name AS ordering_doctor,
|
|---|
| 166 | sp.spec_name AS doctor_specialization,
|
|---|
| 167 | a.appointment_date,
|
|---|
| 168 | a.appointment_type,
|
|---|
| 169 | a.priority_level
|
|---|
| 170 | FROM Laboratory_test lt
|
|---|
| 171 | JOIN Medical_examination me ON me.exam_id = lt.exam_id
|
|---|
| 172 | JOIN Appointment a ON a.appointment_id = me.appointment_id
|
|---|
| 173 | JOIN Patient p ON p.patient_id = lt.patient_id
|
|---|
| 174 | JOIN Doctor d ON d.doctor_id = lt.doctor_id
|
|---|
| 175 | JOIN Specialization sp ON sp.spec_id = d.spec_id;
|
|---|
| 176 |
|
|---|
| 177 | CREATE OR REPLACE VIEW v_prescription_dispensing AS
|
|---|
| 178 | SELECT
|
|---|
| 179 | pr.presc_id,
|
|---|
| 180 | pr.presc_date,
|
|---|
| 181 | p.patient_id,
|
|---|
| 182 | p.first_name || ' ' || p.last_name AS patient_name,
|
|---|
| 183 | p.date_of_birth,
|
|---|
| 184 | d.first_name || ' ' || d.last_name AS prescribing_doctor,
|
|---|
| 185 | sp.spec_name AS doctor_specialization,
|
|---|
| 186 | atc.atc_code,
|
|---|
| 187 | atc.description AS drug_class,
|
|---|
| 188 | dp.producer_name AS manufacturer,
|
|---|
| 189 | dr.unit_price,
|
|---|
| 190 | pr.dosage,
|
|---|
| 191 | pr.duration,
|
|---|
| 192 | round((dr.unit_price * pr.dosage * pr.duration)::NUMERIC, 2) AS estimated_cost,
|
|---|
| 193 | pd.diagnosis_name AS prescribed_for,
|
|---|
| 194 | icd.code AS icd_code
|
|---|
| 195 | FROM Prescription pr
|
|---|
| 196 | JOIN Patient p ON p.patient_id = pr.patient_id
|
|---|
| 197 | JOIN Doctor d ON d.doctor_id = pr.doctor_id
|
|---|
| 198 | JOIN Specialization sp ON sp.spec_id = d.spec_id
|
|---|
| 199 | JOIN ATC_code atc ON atc.atc_id = pr.atc_id
|
|---|
| 200 | JOIN Inventory i ON i.inventory_id = pr.inventory_id
|
|---|
| 201 | JOIN Drug dr ON dr.product_id = i.product_id
|
|---|
| 202 | JOIN Drug_producers dp ON dp.drug_prod_id = dr.drug_prod_id
|
|---|
| 203 | JOIN Patient_diagnosis pd ON pd.patient_diagnosis_id = pr.patient_diagnosis_id
|
|---|
| 204 | JOIN ICD icd ON icd.icd_id = pd.icd_id;
|
|---|
| 205 |
|
|---|
| 206 | CREATE OR REPLACE VIEW v_referral_tracking AS
|
|---|
| 207 | SELECT
|
|---|
| 208 | r.referral_id,
|
|---|
| 209 | p.patient_id,
|
|---|
| 210 | p.first_name || ' ' || p.last_name AS patient_name,
|
|---|
| 211 | ref_dr.first_name || ' ' || ref_dr.last_name AS referring_doctor,
|
|---|
| 212 | ref_sp.spec_name AS referring_specialization,
|
|---|
| 213 | rfd.first_name || ' ' || rfd.last_name AS referred_to_doctor,
|
|---|
| 214 | rfd_sp.spec_name AS referred_specialization,
|
|---|
| 215 | dep.department_name AS referred_department,
|
|---|
| 216 | CASE WHEN EXISTS (
|
|---|
| 217 | SELECT 1 FROM Appointment a
|
|---|
| 218 | WHERE a.referral_id = r.referral_id
|
|---|
| 219 | ) THEN 'YES' ELSE 'NO' END AS appointment_booked,
|
|---|
| 220 | -- Count of appointments from this referral
|
|---|
| 221 | (SELECT COUNT(*) FROM Appointment a
|
|---|
| 222 | WHERE a.referral_id = r.referral_id) AS appointments_count
|
|---|
| 223 | FROM Referral r
|
|---|
| 224 | JOIN Patient p ON p.patient_id = r.patient_id
|
|---|
| 225 | JOIN Doctor ref_dr ON ref_dr.doctor_id = r.referring_doctor_id
|
|---|
| 226 | JOIN Specialization ref_sp ON ref_sp.spec_id = ref_dr.spec_id
|
|---|
| 227 | LEFT JOIN Doctor rfd ON rfd.doctor_id = r.referred_doctor_id
|
|---|
| 228 | LEFT JOIN Specialization rfd_sp ON rfd_sp.spec_id = rfd.spec_id
|
|---|
| 229 | JOIN Department dep ON dep.department_id = r.department_id;
|
|---|
| 230 |
|
|---|
| 231 | CREATE OR REPLACE VIEW v_department_performance AS
|
|---|
| 232 | SELECT
|
|---|
| 233 | dep.department_id,
|
|---|
| 234 | dep.department_name,
|
|---|
| 235 | sp.spec_name AS specialization,
|
|---|
| 236 | COUNT(DISTINCT dd.doctor_id) AS total_doctors,
|
|---|
| 237 | COUNT(DISTINCT CASE WHEN dd.employment_type = 'FULL_TIME'
|
|---|
| 238 | THEN dd.doctor_id END) AS full_time_doctors,
|
|---|
| 239 | COUNT(DISTINCT CASE WHEN dd.employment_type = 'RESIDENT'
|
|---|
| 240 | THEN dd.doctor_id END) AS residents,
|
|---|
| 241 | COUNT(DISTINCT a.appointment_id) AS total_appointments,
|
|---|
| 242 | COUNT(DISTINCT CASE WHEN a.status = 'COMPLETED'
|
|---|
| 243 | THEN a.appointment_id END) AS completed_appointments,
|
|---|
| 244 | COUNT(DISTINCT CASE WHEN a.appointment_type = 'EMERGENCY'
|
|---|
| 245 | THEN a.appointment_id END) AS emergency_appointments,
|
|---|
| 246 | COUNT(DISTINCT a.patient_id) AS unique_patients_seen,
|
|---|
| 247 | COUNT(DISTINCT me.exam_id) AS exams_performed,
|
|---|
| 248 | COUNT(DISTINCT r.referral_id) AS referrals_received,
|
|---|
| 249 | ROUND(
|
|---|
| 250 | 100.0 * COUNT(DISTINCT CASE WHEN a.status = 'COMPLETED'
|
|---|
| 251 | THEN a.appointment_id END)
|
|---|
| 252 | / NULLIF(COUNT(DISTINCT a.appointment_id), 0), 1
|
|---|
| 253 | ) AS completion_rate_pct
|
|---|
| 254 | FROM Department dep
|
|---|
| 255 | JOIN Specialization sp ON sp.spec_id = dep.spec_id
|
|---|
| 256 | LEFT JOIN Doctor_department dd ON dd.department_id = dep.department_id
|
|---|
| 257 | AND dd.date_to IS NULL
|
|---|
| 258 | LEFT JOIN Appointment a ON a.doctor_id IN (
|
|---|
| 259 | SELECT doctor_id FROM Doctor_department
|
|---|
| 260 | WHERE department_id = dep.department_id
|
|---|
| 261 | )
|
|---|
| 262 | LEFT JOIN Medical_examination me ON me.exam_id IN (
|
|---|
| 263 | SELECT me2.exam_id FROM Medical_examination me2
|
|---|
| 264 | JOIN Appointment a2 ON a2.appointment_id = me2.appointment_id
|
|---|
| 265 | WHERE a2.doctor_id IN (
|
|---|
| 266 | SELECT doctor_id FROM Doctor_department
|
|---|
| 267 | WHERE department_id = dep.department_id
|
|---|
| 268 | )
|
|---|
| 269 | )
|
|---|
| 270 | LEFT JOIN Referral r ON r.department_id = dep.department_id
|
|---|
| 271 | GROUP BY dep.department_id, dep.department_name, sp.spec_name; |
|---|