| 7 | | R = {univ_id, univ_name, univ_location, univ_is_private, fac_id, fac_name, fac_location, |
| 8 | | fac_study_field, prof_id, prof_name, prof_surname, prof_age, stud_id, stud_name, |
| 9 | | stud_surname, stud_location, stud_index, subj_id, subj_name, subj_semester, |
| 10 | | subj_credits, ss_id, enrollment_date, final_grade, status, absences_count, |
| 11 | | start_date, end_date} |
| | 7 | R = {univ_id, univ_name, univ_location, univ_is_private, fac_id, fac_name, fac_location, fac_study_field, prof_id, prof_name, prof_surname, prof_age, stud_id, stud_name, stud_surname, stud_location, stud_index, subj_id, subj_name, subj_semester, subj_credits, ss_id, enrollment_date, final_grade, status, absences_count, start_date, end_date} |
| 17 | | * univ_id -> {univ_name, univ_location, univ_is_private} |
| 18 | | * fac_id -> {fac_name, fac_location, fac_study_field, univ_id} |
| 19 | | * prof_id -> {prof_name, prof_surname, prof_age, fac_id} |
| 20 | | * stud_id -> {stud_name, stud_surname, stud_location, stud_index, fac_id} |
| 21 | | * subj_id -> {subj_name, subj_semester, subj_credits, fac_id} |
| 22 | | * {stud_id, prof_id, start_date} -> {end_date} |
| 23 | | * {ss_id, stud_id, subj_id} -> {professor_id, enrollment_date, final_grade, status, absences_count} |
| 24 | | * {univ_id, prof_id} -> (The "Affiliated" relationship table) |
| | 13 | * FD1: univ_id -> {univ_name, univ_location, univ_is_private} |
| | 14 | * FD2: fac_id -> {fac_name, fac_location, fac_study_field, univ_id} |
| | 15 | * FD3: prof_id -> {prof_name, prof_surname, prof_age, fac_id} |
| | 16 | * FD4: stud_id -> {stud_name, stud_surname, stud_location, stud_index, fac_id} |
| | 17 | * FD5: subj_id -> {subj_name, subj_semester, subj_credits, fac_id} |
| | 18 | * FD6: ss_id -> {stud_id, subj_id, prof_id, enrollment_date, final_grade, status, absences_count} |
| | 19 | * FD7: {stud_id, prof_id, start_date} -> {end_date} |
| 32 | | '''Current Normal Form:''' '''1NF'''. The relation is in 1NF because all attributes contain atomic values, but it contains massive update redundancies and partial dependencies. |
| | 30 | * **Step 1 (Base Case):** |
| | 31 | |
| | 32 | K^0 = {ss_id, start_date, univ_id} |
| | 33 | * **Step 2 (Apply FD1):** univ_id -> {univ_name, univ_location, univ_is_private} |
| | 34 | |
| | 35 | K^1 = {ss_id, start_date, univ_id, univ_name, univ_location, univ_is_private} |
| | 36 | * **Step 3 (Apply FD6):** ss_id -> {stud_id, subj_id, prof_id, enrollment_date, final_grade, status, absences_count} |
| | 37 | |
| | 38 | K^2 = {ss_id, start_date, univ_id, univ_name, univ_location, univ_is_private, stud_id, subj_id, prof_id, enrollment_date, final_grade, status, absences_count} |
| | 39 | * **Step 4 (Apply FD3, FD4, FD5):** prof_id, stud_id, and subj_id extract their respective metadata: |
| | 40 | |
| | 41 | K^3 = K^2 + {prof_name, prof_surname, prof_age, fac_id, stud_name, stud_surname, stud_location, stud_index, subj_name, subj_semester, subj_credits} |
| | 42 | * **Step 5 (Apply FD2):** fac_id -> {fac_name, fac_location, fac_study_field, univ_id} |
| | 43 | |
| | 44 | K^4 = K^3 + {fac_name, fac_location, fac_study_field} |
| | 45 | * **Step 6 (Apply FD7):** {stud_id, prof_id, start_date} -> {end_date} |
| | 46 | |
| | 47 | K^5 = K^4 + {end_date} |
| | 48 | |
| | 49 | Since K^5 = R, the set {ss_id, start_date, univ_id} is a valid Superkey. |
| | 50 | |
| | 51 | === Minimality Proof === |
| | 52 | * If we remove ss_id, the closure {start_date, univ_id}+ only yields {start_date, univ_id, univ_name, univ_location, univ_is_private}, failing to find any student, professor, or core entity data. |
| | 53 | * If we remove start_date, the closure cannot resolve end_date via FD7. |
| | 54 | * If we remove univ_id, the closure cannot resolve university and faculty metadata. |
| | 55 | |
| | 56 | Thus, no proper subset is a superkey. The set is strictly minimal. |
| | 57 | |
| | 58 | '''Candidate Key:''' {ss_id, start_date, univ_id} |
| | 59 | '''Primary Key:''' {ss_id, start_date, univ_id} |
| | 60 | |
| | 61 | '''Current Normal Form:''' '''1NF'''. The relation is in 1NF because all attributes contain atomic values, but it contains partial dependencies where non-prime attributes depend on parts of the composite candidate key (e.g., univ_name depends strictly on univ_id, which is only a subset of the main key). |
| 44 | | * '''R1 (Student):''' {stud_id, name, surname, location, index, fac_id} |
| 45 | | * '''R2 (Professor):''' {prof_id, name, surname, age, fac_id} |
| 46 | | * '''R3 (Subject):''' {subj_id, name, semester, credits, fac_id} |
| 47 | | * '''R4 (University):''' {univ_id, name, location, is_private} |
| 48 | | * '''R5 (Faculty):''' {fac_id, name, location, study_field, univ_id} |
| 49 | | * '''R6 (Student_Subject):''' {ss_id, stud_id, subj_id, prof_id, enrollment_date, final_grade, status, absences_count} |
| 50 | | * '''R7 (Advice):''' {stud_id, prof_id, start_date, end_date} |
| 51 | | * '''R8 (Affiliated):''' {univ_id, prof_id} |
| | 73 | * '''Step 2: Isolation of Faculty Entity (Resolving FD2)''' |
| | 74 | * *Violation:* Faculty metadata attributes depend transitively through the hierarchy via fac_id. |
| | 75 | * *Action:* Extract faculty structural descriptors to stop multi-attribute replication. |
| | 76 | * *Result:* '''R2 (Faculty):''' {fac_id, fac_name, fac_location, fac_study_field, univ_id} (Key: fac_id) |
| | 77 | |
| | 78 | * '''Step 3: Isolation of Student Entity (Resolving FD4)''' |
| | 79 | * *Violation:* {stud_name, stud_surname, stud_location, stud_index, fac_id} depend purely on stud_id, which is determined via ss_id (a subset of the primary key's downstream components). This creates an implicit partial dependency in the flattened schema. |
| | 80 | * *Action:* Move student profile vectors to a dedicated entity table. |
| | 81 | * *Result:* '''R3 (Student):''' {stud_id, stud_name, stud_surname, stud_location, stud_index, fac_id} (Key: stud_id) |
| | 82 | |
| | 83 | * '''Step 4: Isolation of Professor Entity (Resolving FD3)''' |
| | 84 | * *Violation:* {prof_name, prof_surname, prof_age, fac_id} depend directly on prof_id. |
| | 85 | * *Action:* Isolate professor demographics away from the transaction logs. |
| | 86 | * *Result:* '''R4 (Professor):''' {prof_id, prof_name, prof_surname, prof_age, fac_id} (Key: prof_id) |
| | 87 | |
| | 88 | * '''Step 5: Isolation of Subject Entity (Resolving FD5)''' |
| | 89 | * *Violation:* Curriculum properties {subj_name, subj_semester, subj_credits, fac_id} depend entirely on subj_id. |
| | 90 | * *Action:* Isolate course syllabus metadata. |
| | 91 | * *Result:* '''R5 (Subject):''' {subj_id, subj_name, subj_semester, subj_credits, fac_id} (Key: subj_id) |
| | 92 | |
| | 93 | * '''Step 6: Isolation of Multi-Attribute Weak Log Relations (Resolving FD6 and FD7)''' |
| | 94 | * *Action:* Separate transactional operational mappings into clean associative tables matching the remaining prime components. |
| | 95 | * *Result (Enrollments):* '''R6 (Student_Subject):''' {ss_id, stud_id, subj_id, prof_id, enrollment_date, final_grade, status, absences_count} (Key: ss_id) |
| | 96 | * *Result (Mentorship):* '''R7 (Advice):''' {stud_id, prof_id, start_date, end_date} (Key: {stud_id, prof_id, start_date}) |
| | 97 | * *Result (Affiliation):* '''R8 (Affiliated):''' {univ_id, prof_id} (Key: {univ_id, prof_id}) |
| | 98 | |
| | 99 | Every non-prime attribute in relations R1 through R8 now depends strictly on the full, complete primary key of its respective table. Partial dependencies are completely eliminated. |