| | 1 | == Напредни извештаи од базата (SQL и складирани процедури) == |
| | 2 | |
| | 3 | === Проценка на присуство за одреден студент === |
| | 4 | |
| | 5 | Прво креираме табела каде што ќе ги чуваме податоците од повикување на процедурата |
| | 6 | {{{ |
| | 7 | #!sql |
| | 8 | CREATE TABLE Attendance_Report ( |
| | 9 | id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| | 10 | student_id UUID NOT NULL, |
| | 11 | start_date DATE NOT NULL, |
| | 12 | end_date DATE NOT NULL, |
| | 13 | present_count INTEGER NOT NULL, |
| | 14 | absent_count INTEGER NOT NULL, |
| | 15 | late_count INTEGER NOT NULL, |
| | 16 | attendance_status VARCHAR(30) NOT NULL, |
| | 17 | generated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, |
| | 18 | FOREIGN KEY (student_id) REFERENCES Ucenik(id) |
| | 19 | ); |
| | 20 | }}} |
| | 21 | |
| | 22 | Следно креираме процедура за броење на |
| | 23 | * бројот на "ZADOCNET" |
| | 24 | * бројот на "PRISUTEN" |
| | 25 | * бројот на "OTSUTEN" |
| | 26 | |
| | 27 | И потоа пресметуваме според одредена логика за просечна вредност која што може да биде |
| | 28 | * REDOVEN |
| | 29 | * POVREMENO_OTSUTEN |
| | 30 | * NEREDOVEN |
| | 31 | |
| | 32 | |
| | 33 | |
| | 34 | {{{ |
| | 35 | #!sql |
| | 36 | CREATE OR REPLACE PROCEDURE generate_attendance_report( |
| | 37 | p_start_date DATE, |
| | 38 | p_end_date DATE |
| | 39 | ) |
| | 40 | LANGUAGE plpgsql |
| | 41 | AS $$ |
| | 42 | DECLARE |
| | 43 | r RECORD; |
| | 44 | v_status VARCHAR(30); |
| | 45 | |
| | 46 | BEGIN |
| | 47 | |
| | 48 | DELETE FROM Attendance_Report -- go briseme prethodniot zapis |
| | 49 | WHERE start_date = p_start_date |
| | 50 | AND end_date = p_end_date; |
| | 51 | |
| | 52 | FOR r IN |
| | 53 | SELECT |
| | 54 | p.seOdnesuvaNaUcenikot_Id AS student_id, |
| | 55 | |
| | 56 | COUNT(*) FILTER ( |
| | 57 | WHERE p.status = 'PRISUTEN' |
| | 58 | )::INTEGER AS present_count, |
| | 59 | |
| | 60 | COUNT(*) FILTER ( |
| | 61 | WHERE p.status = 'OTSUTEN' |
| | 62 | )::INTEGER AS absent_count, |
| | 63 | |
| | 64 | COUNT(*) FILTER ( |
| | 65 | WHERE p.status = 'ZADOCNET' |
| | 66 | )::INTEGER AS late_count |
| | 67 | |
| | 68 | FROM Prisustvo p |
| | 69 | |
| | 70 | WHERE p.datum BETWEEN p_start_date AND p_end_date |
| | 71 | |
| | 72 | GROUP BY p.seOdnesuvaNaUcenikot_Id |
| | 73 | |
| | 74 | LOOP |
| | 75 | |
| | 76 | IF r.absent_count = 0 |
| | 77 | AND r.late_count <= 2 THEN |
| | 78 | |
| | 79 | v_status := 'REDOVEN'; |
| | 80 | |
| | 81 | ELSIF r.absent_count <= 3 |
| | 82 | AND r.late_count <= 5 THEN |
| | 83 | |
| | 84 | v_status := 'POVREMENO_OTSUTEN'; |
| | 85 | |
| | 86 | ELSE |
| | 87 | |
| | 88 | v_status := 'NEREDOVEN'; |
| | 89 | |
| | 90 | END IF; |
| | 91 | |
| | 92 | |
| | 93 | INSERT INTO Attendance_Report ( |
| | 94 | student_id, |
| | 95 | start_date, |
| | 96 | end_date, |
| | 97 | present_count, |
| | 98 | absent_count, |
| | 99 | late_count, |
| | 100 | attendance_status |
| | 101 | ) |
| | 102 | VALUES ( |
| | 103 | r.student_id, |
| | 104 | p_start_date, |
| | 105 | p_end_date, |
| | 106 | r.present_count, |
| | 107 | r.absent_count, |
| | 108 | r.late_count, |
| | 109 | v_status |
| | 110 | ); |
| | 111 | |
| | 112 | END LOOP; |
| | 113 | |
| | 114 | END; |
| | 115 | $$; |
| | 116 | |
| | 117 | }}} |
| | 118 | |
| | 119 | Откако ќе се внесат неколку присуства, може да ја повикаме процедурата: |
| | 120 | {{{ |
| | 121 | #!sql |
| | 122 | CALL generate_attendance_report( '2026-01-01', '2026-12-31' ); --datum od, datum do odnosno cela godina |
| | 123 | }}} |
| | 124 | |
| | 125 | |
| | 126 | Потоа можеме да ги извлечеме резултатите: |
| | 127 | |
| | 128 | {{{ |
| | 129 | #!sql |
| | 130 | SELECT |
| | 131 | student_id, |
| | 132 | start_date, |
| | 133 | end_date, |
| | 134 | present_count, |
| | 135 | absent_count, |
| | 136 | late_count, |
| | 137 | attendance_status, |
| | 138 | generated_at, |
| | 139 | k.ime, |
| | 140 | k.prezime |
| | 141 | FROM Attendance_Report |
| | 142 | JOIN Korisnik k ON k.id = student_id |
| | 143 | ORDER BY attendance_status, student_id |
| | 144 | }}} |
| | 145 | |
| | 146 | |