QueryOptimization: views.sql

File views.sql, 19.8 KB (added by 231039, 10 days ago)
Line 
1-- ============================================================
2-- View 1: daily_clinic_schedule
3--
4-- Primary filter: date_appointment and employee_id
5-- ============================================================
6
7CREATE OR REPLACE VIEW daily_clinic_schedule AS
8SELECT
9 a.id AS appointment_id,
10 a.date_appointment,
11 a.reason,
12 o.id AS owner_id,
13 o.first_name || ' ' || o.last_name AS owner_name,
14 o.phone AS owner_phone,
15 p.id AS pet_id,
16 p.name AS pet_name,
17 p.type AS pet_type,
18 e.id AS examination_id,
19 e.status AS examination_status,
20 emp.id AS employee_id,
21 emp.first_name || ' ' || emp.last_name AS employee_name,
22 rl.name AS employee_role,
23 er.id AS room_id,
24 er.room_number,
25 er.type AS room_type
26FROM appointment a
27JOIN owner o ON o.id = a.owner_id
28JOIN pet p ON p.id = a.pet_id
29LEFT JOIN examination e ON e.appointment_id = a.id
30LEFT JOIN employee emp ON emp.id = e.employee_id
31LEFT JOIN role rl ON rl.id = emp.role_id
32LEFT JOIN examination_room er ON er.id = e.examination_room_id;
33
34SELECT * FROM daily_clinic_schedule WHERE date_appointment = '2025-07-07';
35EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM daily_clinic_schedule WHERE date_appointment = '2025-07-07';
36
37SELECT * FROM daily_clinic_schedule
38WHERE employee_id = 3 AND date_appointment = '2025-07-07';
39EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM daily_clinic_schedule
40WHERE employee_id = 3 AND date_appointment = '2025-07-07';
41
42-- INSERT into appointment
43INSERT INTO appointment (date_appointment, reason, phone, owner_id, pet_id)
44VALUES ('2025-07-07', 'Routine checkup', '+389 71 271 919', 1, 385);
45-- UPDATE on appointment
46UPDATE appointment
47SET reason = 'Follow-up visit'
48WHERE date_appointment = '2025-07-07' AND owner_id = 1;
49
50-- INSERT into examination
51INSERT INTO examination (date_examination, status, appointment_id, employee_id, examination_room_id)
52VALUES ('2025-07-10', 'scheduled', 850801, 3, 5);
53-- UPDATE on examination
54UPDATE examination
55SET status = 'completed'
56WHERE employee_id = 3 AND date_examination = '2025-07-10';
57
58-- INDEXES
59-- CREATE INDEX idx_examination_employee on examination (employee_id);
60DROP INDEX IF EXISTS idx_examination_employee;
61CREATE INDEX idx_appointment_date on appointment (date_appointment);
62CREATE INDEX idx_examination_appointment ON examination (appointment_id);
63
64-- INSERT into appointment
65INSERT INTO appointment (date_appointment, reason, phone, owner_id, pet_id)
66VALUES ('2025-07-08', 'Vaccination check', '+389 77 979 331', 2, 230);
67-- UPDATE on appointment
68UPDATE appointment
69SET reason = 'Vaccination follow-up visit'
70WHERE date_appointment = '2025-07-08' AND owner_id = 2;
71
72-- INSERT into examination
73INSERT INTO examination (date_examination, status, appointment_id, employee_id, examination_room_id)
74VALUES ('2025-07-15', 'scheduled', 850802, 3, 5);
75-- UPDATE on examination
76UPDATE examination
77SET status = 'completed'
78WHERE employee_id = 3 AND date_examination = '2025-07-15';
79
80
81-- ============================================================
82-- View 2: pet_medical_history
83--
84-- Primary filter: pet_id (also usable by owner_id, date_examination)
85-- Use case: vet or assistant pulls up a pet's full medical timeline
86-- during a visit: appointments, examinations, and every treatment
87-- (consultation/vaccination/prescription/operation) with its
88-- type-specific attributes collapsed into one JSON blob, since
89-- each treatment_type has a different attribute set (EAV pattern).
90-- ============================================================
91
92CREATE OR REPLACE VIEW pet_medical_history AS
93SELECT
94 p.id AS pet_id,
95 p.name AS pet_name,
96 p.type AS pet_type,
97 p.breed,
98 p.age,
99 o.id AS owner_id,
100 o.first_name || ' ' || o.last_name AS owner_name,
101 o.phone AS owner_phone,
102 a.id AS appointment_id,
103 a.date_appointment,
104 a.reason AS appointment_reason,
105 e.id AS examination_id,
106 e.date_examination,
107 e.status AS examination_status,
108 e.description AS examination_notes,
109 emp.id AS employee_id,
110 emp.first_name || ' ' || emp.last_name AS attending_employee,
111 r.name AS employee_role,
112 t.id AS treatment_id,
113 t.date_treatment,
114 tt.name AS treatment_type,
115 t.notes AS treatment_notes,
116 (
117 SELECT json_object_agg(ta.name, tav.value)
118 FROM treatment_attribute_value tav
119 JOIN treatment_attribute ta ON ta.id = tav.treatment_attribute_id
120 WHERE tav.treatment_id = t.id
121 ) AS treatment_details
122FROM pet p
123JOIN owner o ON o.id = p.owner_id
124LEFT JOIN appointment a ON a.pet_id = p.id
125LEFT JOIN examination e ON e.appointment_id = a.id
126LEFT JOIN employee emp ON emp.id = e.employee_id
127LEFT JOIN role r ON r.id = emp.role_id
128LEFT JOIN treatment t ON t.examination_id = e.id
129LEFT JOIN treatment_type tt ON tt.id = t.treatment_type_id;
130
131SELECT * FROM pet_medical_history WHERE pet_id = 9956;
132EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM pet_medical_history WHERE pet_id = 9956;
133
134SELECT id, treatment_type_id, examination_id FROM treatment LIMIT 5;
135
136-- INSERT into treatment, treatment_attribute_value
137INSERT INTO treatment (examination_id, treatment_type_id, date_treatment, notes)
138VALUES (1726, 2, CURRENT_DATE, 'Follow-up dosage adjustment');
139-- SELECT max(id) FROM treatment
140
141INSERT INTO treatment_attribute_value (treatment_id, treatment_attribute_id, value)
142VALUES (577416, 13, 'false');
143
144-- UPDATE treatment, treatment_attribute_value
145
146-- SELECT tav.treatment_id, tav.value
147-- FROM treatment_attribute_value tav
148-- JOIN treatment t ON t.id = tav.treatment_id
149-- WHERE t.treatment_type_id = 4
150-- AND tav.treatment_attribute_id = 23
151-- LIMIT 5;
152
153UPDATE treatment
154SET notes = 'Updated post-op notes'
155WHERE id = 1577;
156
157UPDATE treatment_attribute_value
158SET value = '122'
159WHERE treatment_id = 1577 AND treatment_attribute_id = 23;
160
161CREATE INDEX idx_appointment_pet ON appointment (pet_id);
162-- CREATE INDEX idx_treatment_attribute_value_treatment ON treatment_attribute_value (treatment_id);
163DROP INDEX IF EXISTS idx_treatment_attribute_value_treatment;
164
165-- INSERT into treatment, treatment_attribute_value
166INSERT INTO treatment (examination_id, treatment_type_id, date_treatment, notes)
167VALUES (1726, 2, CURRENT_DATE, 'Second follow-up dosage adjustment');
168-- SELECT max(id) FROM treatment;
169
170INSERT INTO treatment_attribute_value (treatment_id, treatment_attribute_id, value)
171VALUES (577417, 13, 'false');
172
173-- UPDATE treatment, treatment_attribute_value
174UPDATE treatment
175SET notes = 'Updated dosage per second follow-up'
176WHERE id = 1570;
177
178UPDATE treatment_attribute_value
179SET value = 'true'
180WHERE treatment_id = 1571 AND treatment_attribute_id = 13;
181
182
183-- ============================================================
184-- View 3: active_prescriptions_for_pet
185--
186-- Primary filter: pet_id (also usable by medicine_id)
187-- Use case: pet_id - vet checks what a pet is currently prescribed
188-- before adding a new treatment, to catch interactions or repeat
189-- prescriptions. medicine_id - clinic checks which currently
190-- active patients are on a given medicine, during a
191-- medication recall or an interaction check. Filters to
192-- prescriptions where today falls within date_start/date_end.
193-- ============================================================
194
195CREATE OR REPLACE VIEW active_prescriptions_for_pet AS
196SELECT
197 p.id AS pet_id,
198 p.name AS pet_name,
199 o.id AS owner_id,
200 o.first_name || ' ' || o.last_name AS owner_name,
201 pr.id AS prescription_id,
202 pr.date_start,
203 pr.date_end,
204 pr.description AS prescription_notes,
205 m.id AS medicine_id,
206 m.name AS medicine_name,
207 pm.dosage,
208 pm.num_days
209FROM pet p
210JOIN appointment a ON a.pet_id = p.id
211JOIN owner o ON o.id = p.owner_id
212JOIN examination e ON e.appointment_id = a.id
213JOIN prescription pr ON pr.examination_id = e.id
214JOIN prescription_medicine pm ON pm.prescription_id = pr.id
215JOIN medicine m ON m.id = pm.medicine_id
216WHERE pr.date_start <= CURRENT_DATE AND pr.date_end >= CURRENT_DATE;
217
218-- 1. By pet (idx_appointment_pet + PK on prescription_medicine)
219SELECT * FROM active_prescriptions_for_pet WHERE pet_id = 3;
220EXPLAIN (ANALYZE, BUFFERS)
221SELECT * FROM active_prescriptions_for_pet WHERE pet_id = 3;
222
223-- 2. By medicine (seq scan)
224SELECT * FROM active_prescriptions_for_pet WHERE medicine_id = 47;
225EXPLAIN (ANALYZE, BUFFERS)
226SELECT * FROM active_prescriptions_for_pet WHERE medicine_id = 47;
227
228-- INSERT into prescription, prescription_medicine
229INSERT INTO prescription (examination_id, date_start, date_end, description)
230VALUES (699, CURRENT_DATE, CURRENT_DATE + 10, 'Antibiotic course, 10 days');
231-- SELECT max(id) FROM prescription;
232
233INSERT INTO prescription_medicine (prescription_id, medicine_id, dosage, num_days)
234VALUES (432525, 1, 250, 10);
235
236-- UPDATE on prescription, prescription_medicine
237UPDATE prescription
238SET date_end = date_end + 5
239WHERE id = 328;
240
241UPDATE prescription_medicine
242SET dosage = 300
243WHERE prescription_id = 327 AND medicine_id = 8;
244
245-- CREATE INDEX idx_prescription_active_dates ON prescription (date_end, date_start);
246DROP INDEX IF EXISTS idx_prescription_active_dates;
247
248-- INSERT into prescription, prescription_medicine
249INSERT INTO prescription (examination_id, date_start, date_end, description)
250VALUES (700, CURRENT_DATE, CURRENT_DATE + 7, 'Follow-up course');
251-- SELECT max(id) FROM prescription;
252
253INSERT INTO prescription_medicine (prescription_id, medicine_id, dosage, num_days)
254VALUES (432526, 2, 200, 7);
255
256-- UPDATE on prescription, prescription_medicine
257UPDATE prescription
258SET date_end = date_end + 3
259WHERE id = 329;
260
261UPDATE prescription_medicine
262SET dosage = 150
263WHERE prescription_id = 329 AND medicine_id = 6756;
264
265-- ============================================================
266-- View 4: employee_performance_summary
267--
268-- Primary filter: employee_id (also usable by date_treatment range)
269-- Use case: management pulls a per-employee workload record.
270-- Every examination they conducted, every treatment tied to it,
271-- and what that treatment was billed at in order to review caseload
272-- and revenue contribution per vet/assistant.
273-- ============================================================
274
275-- DROP VIEW IF EXISTS employee_performance_summary;
276
277CREATE MATERIALIZED VIEW employee_performance_summary AS
278SELECT
279 emp.id AS employee_id,
280 emp.first_name || ' ' || emp.last_name AS employee_name,
281 rl.name AS employee_role,
282 e.id AS examination_id,
283 e.date_examination,
284 e.status AS examination_status,
285 t.id AS treatment_id,
286 tt.name AS treatment_type,
287 t.date_treatment,
288 ii.price AS billed_price,
289 ii.invoice_id
290FROM employee emp
291 JOIN role rl ON rl.id = emp.role_id
292 LEFT JOIN examination e ON e.employee_id = emp.id
293 LEFT JOIN treatment t ON t.examination_id = e.id
294 LEFT JOIN treatment_type tt ON tt.id = t.treatment_type_id
295 LEFT JOIN invoice_item ii ON ii.treatment_id = t.id;
296
297SELECT * FROM employee_performance_summary WHERE employee_id = 5;
298EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM employee_performance_summary WHERE employee_id = 5;
299
300SELECT * FROM employee_performance_summary
301WHERE employee_id = 5 AND date_treatment >= '2025-01-01' AND date_treatment < '2026-01-01';
302EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM employee_performance_summary
303 WHERE employee_id = 5 AND date_treatment >= '2025-01-01' AND date_treatment < '2026-01-01';
304
305--INSERT into examination
306INSERT INTO examination(date_examination, status, description, appointment_id, employee_id, examination_room_id)
307VALUES ('2026-08-01','completed','Regular check-up', 720800,6,3);
308
309--INSERT into treatment
310INSERT INTO treatment(date_treatment, notes, treatment_type_id, examination_id)
311VALUES ('2026-08-01','Follow-up plan agreed',2,715);
312
313--INSERT into invoice
314INSERT INTO invoice(date_invoice, total, coupon_id, owner_id)
315VALUES ('2026-08-01',56.33,398,79);
316
317--INSERT into invoice_item
318INSERT INTO invoice_item(num_item, invoice_id, price,quantity, type, shop_item_id, treatment_id)
319VALUES (1,24972,67.87,1,'treatment',null,223433);
320
321--UPDATE on treatment
322UPDATE treatment
323SET notes = 'Updated: discussed follow-up diet plan'
324WHERE id = 5778001;
325
326CREATE INDEX idx_treatment_examination ON treatment (examination_id);
327-- CREATE INDEX idx_treatment_date ON treatment (date_treatment);
328-- CREATE INDEX idx_invoice_item_treatment ON invoice_item (treatment_id);
329DROP INDEX IF EXISTS idx_treatment_date;
330DROP INDEX IF EXISTS idx_invoice_item_treatment;
331
332-- INSERT into examination (second follow-up)
333INSERT INTO examination(date_examination, status, description, appointment_id, employee_id, examination_room_id)
334VALUES ('2026-08-01','completed','Follow-up check-up', 720800,6,3);
335
336--INSERT into treatment (second follow-up)
337INSERT INTO treatment(date_treatment, notes, treatment_type_id, examination_id)
338VALUES ('2026-08-01','Follow-up plan discussed',2,715);
339
340UPDATE treatment
341SET notes = 'Updated after second follow-up'
342WHERE id = 5778002;
343
344-- ============================================================
345-- View 5: invoice_billing_details
346--
347-- Primary filter: invoice_id (also works by owner_id)
348-- Use case: front-desk/billing staff pull up everything on an
349-- invoice — owner, coupon applied, every line item (shop item
350-- or treatment), and payments received, to answer the question "what does
351-- this owner still owe" or reprint a receipt.
352-- ============================================================
353
354CREATE OR REPLACE VIEW invoice_billing_details AS
355SELECT
356 i.id AS invoice_id,
357 i.date_invoice,
358 i.total AS invoice_total,
359 o.id AS owner_id,
360 o.first_name || ' ' || o.last_name AS owner_name,
361 o.phone AS owner_phone,
362 c.code AS coupon_code,
363 c.type AS coupon_type,
364 c.value AS coupon_value,
365 ii.num_item,
366 ii.type AS line_type,
367 ii.price AS line_price,
368 ii.quantity,
369 si.name AS shop_item_name,
370 tr.id AS treatment_id,
371 tt.name AS treatment_type,
372 p.date_payment,
373 p.amount AS amount_paid,
374 p.method AS payment_method
375FROM invoice i
376 JOIN owner o ON o.id = i.owner_id
377 LEFT JOIN coupon c ON c.id = i.coupon_id
378 LEFT JOIN invoice_item ii ON ii.invoice_id = i.id
379 LEFT JOIN shop_item si ON si.id = ii.shop_item_id
380 LEFT JOIN treatment tr ON tr.id = ii.treatment_id
381 LEFT JOIN treatment_type tt ON tt.id = tr.treatment_type_id
382 LEFT JOIN payment p ON p.invoice_id = i.id;
383
384SELECT * FROM invoice_billing_details WHERE invoice_id = 500000;
385EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM invoice_billing_details WHERE invoice_id = 500000;
386
387SELECT * FROM invoice_billing_details WHERE owner_id = 45;
388EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM invoice_billing_details WHERE owner_id = 45;
389
390-- INSERT into invoice
391INSERT INTO invoice (date_invoice, total, coupon_id, owner_id)
392VALUES (CURRENT_DATE, 62.50, NULL, 8);
393
394-- INSERT into invoice_item
395INSERT INTO invoice_item (num_item, invoice_id, price,quantity, type, shop_item_id, treatment_id)
396VALUES (1, 24984,62.50, 1, 'shop_item', 9,null);
397
398-- INSERT into payment
399INSERT INTO payment (date_payment, amount, method, invoice_id)
400VALUES (CURRENT_DATE, 62.50, 'credit card', 24984);
401
402-- UPDATE on invoice
403UPDATE invoice
404SET total = 58.00
405WHERE id = 24984;
406
407-- UPDATE on payment
408UPDATE payment
409SET amount = 58.00
410WHERE invoice_id = 24984;
411
412--Creating indexes
413CREATE INDEX idx_invoice_owner ON invoice (owner_id);
414CREATE INDEX idx_payment_invoice ON payment (invoice_id);
415-- CREATE INDEX idx_invoice_item_invoice_id ON invoice_item (invoice_id, num_item);
416DROP INDEX IF EXISTS idx_invoice_item_invoice_id;
417
418
419-- INSERT into invoice (second invoice)
420INSERT INTO invoice (date_invoice, total, coupon_id, owner_id)
421VALUES (CURRENT_DATE, 69.50, NULL, 8);
422
423-- INSERT into invoice_item (second invoice)
424INSERT INTO invoice_item (num_item, invoice_id, price,quantity, type, shop_item_id, treatment_id)
425VALUES (1, 24984,69.50, 1, 'shop_item', 9,null);
426
427-- INSERT into payment (second invoice)
428INSERT INTO payment (date_payment, amount, method, invoice_id)
429VALUES (CURRENT_DATE, 50.00, 'credit card', 24984);
430
431UPDATE invoice
432SET total = 27.00
433WHERE id = 24984;
434
435-- ============================================================
436-- View 6: low_stock_shop_items
437--
438-- Primary filter: category_name (also usable by a stock threshold)
439-- Use case: shop manager checks what needs reordering. Any item
440-- with fewer than 20 units left, grouped by category so they
441-- can restock by supplier/category in one trip.
442-- ============================================================
443
444CREATE OR REPLACE VIEW low_stock_shop_items AS
445SELECT
446 si.id AS shop_item_id,
447 si.name AS item_name,
448 si.price,
449 si.stock,
450 sic.id AS category_id,
451 sic.name AS category_name,
452 parent.name AS parent_category_name
453FROM shop_item si
454 JOIN shop_item_category sic ON sic.id = si.shop_item_category_id
455 LEFT JOIN shop_item_category parent ON parent.id = sic.parent_id
456WHERE si.stock < 20;
457
458SELECT * FROM low_stock_shop_items WHERE category_name = 'Medicine';
459EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM low_stock_shop_items WHERE category_name = 'Medicine';
460
461SELECT * FROM low_stock_shop_items WHERE stock < 10;
462EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM low_stock_shop_items WHERE stock < 10;
463
464-- INSERT a new item that's already low on stock
465INSERT INTO shop_item (name, price, stock, shop_item_category_id)
466SELECT 'Emergency Saline Restock Pack', 12.99, 8, sic.id
467FROM shop_item_category sic
468WHERE sic.name = 'Medicine'
469LIMIT 1;
470
471-- UPDATE — simulate a sale reducing stock on an existing item
472UPDATE shop_item
473SET stock = stock - 5
474WHERE id = (SELECT id FROM shop_item WHERE name = 'Emergency Saline Restock Pack');
475
476-- second restock scenario
477UPDATE shop_item
478SET stock = stock - 3
479WHERE id = (SELECT id FROM shop_item WHERE name = 'Emergency Saline Restock Pack');
480
481INSERT INTO shop_item (name, price, stock, shop_item_category_id)
482SELECT 'Sample Low-Stock Toy', 6.49, 4, sic.id
483FROM shop_item_category sic
484WHERE sic.name = 'Toys'
485LIMIT 1;