Changes between Initial Version and Version 1 of Normalization


Ignore:
Timestamp:
09/24/26 09:30:38 (3 days ago)
Author:
236024
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v1 v1  
     1= Normalization =
     2
     3This page presents the normalization of the BEST Skopje Hub relational model from one unified de-normalized relation through 1NF, 2NF, 3NF and BCNF.
     4
     5== De-normalized database form ==
     6
     7=== Unified de-normalized relation ===
     8
     9{{{
     10U(
     11    announced_at, application_id, application_status, application_type,
     12    as_id, as_start_time, at_description, at_id, at_name,
     13    attendance_status, birthday, c_id, c_name, cooperation_type,
     14    ee_end_time, ee_id, ee_start_time, ee_title, ef_no, eft_id, eft_name,
     15    es_no, es_start_time, es_title, est_description, est_id, est_name,
     16    et_description, et_id, et_name, email, faculty, field_of_studies,
     17    first_name, fm_id, l_id, l_name, last_name, mandate_year,
     18    mentor_index, motivational_letter, ms_id, ms_name, msr_id,
     19    naframa_reference, needed_no_volunteers, of_id, of_title,
     20    phone_number, reason, rsvp_at, rsvp_status, student_index,
     21    valid_from, valid_to, volunteer_role, year_of_studies
     22)
     23}}}
     24
     25=== Functional dependencies ===
     26
     27The global functional dependencies for `U` are:
     28
     29{{{
     30student_index -> first_name, last_name, faculty, field_of_studies,
     31                 year_of_studies, birthday, email, phone_number, mentor_index
     32
     33ms_id -> ms_name
     34ms_name -> ms_id
     35msr_id -> student_index, ms_id, valid_from, valid_to
     36
     37of_id -> of_title
     38of_title -> of_id
     39fm_id -> student_index, of_id, mandate_year
     40
     41at_id -> at_name, at_description
     42at_name -> at_id
     43l_id -> l_name
     44l_name -> l_id
     45et_id -> et_name, et_description
     46et_name -> et_id
     47est_id -> est_name, est_description
     48est_name -> est_id
     49eft_id -> eft_name
     50eft_name -> eft_id
     51
     52as_id -> at_id, l_id, as_start_time, ee_id
     53ee_id -> et_id, ee_title, ee_start_time, ee_end_time
     54(ee_id, es_no) -> est_id, l_id, es_start_time, es_title,
     55                     needed_no_volunteers
     56(ee_id, ef_no) -> eft_id
     57
     58application_id -> student_index, ee_id, ef_no, motivational_letter,
     59                  application_type, application_status
     60(student_index, as_id) -> rsvp_status, rsvp_at, attendance_status,
     61                          reason, announced_at
     62(student_index, ee_id, es_no) -> volunteer_role
     63c_id -> c_name, naframa_reference
     64(c_id, ee_id) -> cooperation_type
     65}}}
     66
     67=== Canonical cover ===
     68
     69The canonical cover `Fc` is:
     70
     71{{{
     72student_index -> first_name
     73student_index -> last_name
     74student_index -> faculty
     75student_index -> field_of_studies
     76student_index -> year_of_studies
     77student_index -> birthday
     78student_index -> email
     79student_index -> phone_number
     80student_index -> mentor_index
     81ms_id -> ms_name
     82ms_name -> ms_id
     83msr_id -> student_index
     84msr_id -> ms_id
     85msr_id -> valid_from
     86msr_id -> valid_to
     87of_id -> of_title
     88of_title -> of_id
     89fm_id -> student_index
     90fm_id -> of_id
     91fm_id -> mandate_year
     92at_id -> at_name
     93at_id -> at_description
     94at_name -> at_id
     95l_id -> l_name
     96l_name -> l_id
     97et_id -> et_name
     98et_id -> et_description
     99et_name -> et_id
     100est_id -> est_name
     101est_id -> est_description
     102est_name -> est_id
     103eft_id -> eft_name
     104eft_name -> eft_id
     105as_id -> at_id
     106as_id -> l_id
     107as_id -> as_start_time
     108as_id -> ee_id
     109ee_id -> et_id
     110ee_id -> ee_title
     111ee_id -> ee_start_time
     112ee_id -> ee_end_time
     113(ee_id, es_no) -> est_id
     114(ee_id, es_no) -> l_id
     115(ee_id, es_no) -> es_start_time
     116(ee_id, es_no) -> es_title
     117(ee_id, es_no) -> needed_no_volunteers
     118(ee_id, ef_no) -> eft_id
     119application_id -> student_index
     120application_id -> ee_id
     121application_id -> ef_no
     122application_id -> motivational_letter
     123application_id -> application_type
     124application_id -> application_status
     125(student_index, as_id) -> rsvp_status
     126(student_index, as_id) -> rsvp_at
     127(student_index, as_id) -> attendance_status
     128(student_index, as_id) -> reason
     129(student_index, as_id) -> announced_at
     130(student_index, ee_id, es_no) -> volunteer_role
     131c_id -> c_name
     132c_id -> naframa_reference
     133(c_id, ee_id) -> cooperation_type
     134}}}
     135
     136`|Fc| = 62`. No left-hand-side attribute is extraneous and no dependency is redundant.
     137
     138=== Candidate keys and primary key ===
     139
     140{{{
     141CandidateKeys(U) = {
     142    {application_id, as_id, c_id, fm_id, msr_id, es_no}
     143}
     144
     145PrimaryKey(U) =
     146    {application_id, as_id, c_id, fm_id, msr_id, es_no}
     147}}}
     148
     149The six attributes in the displayed key do not occur on the right-hand side of any dependency in `Fc`, so every candidate key must contain all six. Their closure contains all 57 attributes of `U`. Removing any one of them leaves that attribute outside the closure, which proves that the set is minimal and that no other candidate key exists.
     150
     151== 1NF decomposition ==
     152
     153All 57 attributes of `U` are atomic. Multiple locations are represented by separate `(ee_id, l_id)` combinations rather than by a list in one attribute.
     154
     155Therefore `U` is already in 1NF and no decomposition is needed at this step.
     156
     157`U` is not in 2NF. Partial dependencies include:
     158
     159{{{
     160application_id -> motivational_letter
     161msr_id -> valid_from
     162fm_id -> mandate_year
     163as_id -> as_start_time
     164c_id -> c_name
     165}}}
     166
     167== 2NF decomposition ==
     168
     169The key of `U` is `(application_id, as_id, c_id, fm_id, msr_id, es_no)`. The dependencies shown below have determinants that are proper subsets of this key, so they are the starting points for the 2NF decomposition.
     170
     171The names follow the project terminology. The suffix `_2NF` marks an intermediate relation that still contains transitively determined descriptive attributes and will be divided further in the 3NF step.
     172
     173|| Intermediate relation || Key || Functional dependencies that apply ||
     174|| `applications_2NF` || `application_id` || `application_id` determines the application, student, event edition and event function data ||
     175|| `membership_stage_records_2NF` || `msr_id` || `msr_id -> student_index, ms_id, valid_from, valid_to`, with `ms_id -> ms_name` ||
     176|| `function_mandates_2NF` || `fm_id` || `fm_id -> student_index, of_id, mandate_year`, with `of_id -> of_title` ||
     177|| `activity_sessions_2NF` || `as_id` || `as_id -> at_id, l_id, as_start_time, ee_id`, with the activity-type and location descriptions ||
     178|| `event_editions_2NF` || `ee_id` || `ee_id -> et_id, ee_title, ee_start_time, ee_end_time`, with the event-type description ||
     179|| `event_sessions_2NF` || `(ee_id, es_no)` || the key determines the event-session data, event-session-type description and location name ||
     180|| `event_functions_2NF` || `(ee_id, ef_no)` || `(ee_id, ef_no) -> eft_id`, with `eft_id -> eft_name` ||
     181|| `participation` || `(student_index, as_id)` || the key determines `rsvp_status`, `rsvp_at` and `attendance_status` ||
     182|| `announces_absence` || `(student_index, as_id)` || the key determines `reason` and `announced_at` ||
     183|| `volunteers` || `(student_index, ee_id, es_no)` || the key determines `volunteer_role` ||
     184|| `companies` || `c_id` || `c_id -> c_name, naframa_reference` ||
     185|| `cooperation` || `(c_id, ee_id)` || the key determines `cooperation_type` ||
     186
     187Each extracted relation contains its displayed determinant and the attributes dependent on it. The determinant is the complete key of the extracted relation, while it remains in the other relation as the common join attribute. This removes the partial dependencies from `U`; the resulting intermediate relations are in 2NF.
     188
     189Remaining transitive dependencies:
     190
     191{{{
     192application_id -> student_index -> first_name
     193msr_id -> ms_id -> ms_name
     194fm_id -> of_id -> of_title
     195as_id -> at_id -> at_name
     196ee_id -> et_id -> et_name
     197(ee_id, es_no) -> est_id -> est_name
     198(ee_id, es_no) -> l_id -> l_name
     199(ee_id, ef_no) -> eft_id -> eft_name
     200}}}
     201
     202== 3NF decomposition ==
     203
     204The `_2NF` relations still contain descriptive attributes reached through another non-key attribute. For example, `msr_id -> ms_id` and `ms_id -> ms_name` place `ms_name` transitively under `msr_id`. The following decompositions remove those transitive dependencies:
     205
     206|| Relation analyzed || Dependency causing the 3NF issue || Relations obtained || Keys after decomposition ||
     207|| `applications_2NF` || `application_id -> student_index -> student data` || `applications`, `students` || `application_id`; `student_index` ||
     208|| `membership_stage_records_2NF` || `msr_id -> ms_id -> ms_name` || `membership_stage_records`, `membership_stages` || `msr_id`; `ms_id` and `ms_name` ||
     209|| `function_mandates_2NF` || `fm_id -> of_id -> of_title` || `function_mandates`, `organizational_functions` || `fm_id`; `of_id` and `of_title` ||
     210|| `activity_sessions_2NF` || `as_id -> at_id -> at_name, at_description`; `as_id -> l_id -> l_name` || `activity_sessions`, `activity_types`, `locations` || `as_id`; `at_id` and `at_name`; `l_id` and `l_name` ||
     211|| `event_editions_2NF` || `ee_id -> et_id -> et_name, et_description` || `event_editions`, `event_types` || `ee_id`; `et_id` and `et_name` ||
     212|| `event_sessions_2NF` || `(ee_id, es_no) -> est_id -> est_name, est_description`; `(ee_id, es_no) -> l_id -> l_name` || `event_sessions`, `event_session_types`, `locations` || `(ee_id, es_no)`; `est_id` and `est_name`; `l_id` and `l_name` ||
     213|| `event_functions_2NF` || `(ee_id, ef_no) -> eft_id -> eft_name` || `event_functions`, `event_function_types` || `(ee_id, ef_no)`; `eft_id` and `eft_name` ||
     214
     215In each row, the determinant of the transitive dependency becomes a key of its own relation and remains as a foreign key in the referencing relation. After these decompositions, no non-primary attribute is transitively dependent on a candidate key, so the relations are in 3NF.
     216
     217== BCNF ==
     218
     219|| Relation group || Candidate key or keys || BCNF check ||
     220|| `students` || `student_index` || the key determines the student attributes ||
     221|| `members`, `observers`, `full_members`, `alumni` || `student_index` || no non-trivial functional dependency has a non-key left-hand side ||
     222|| `young_members` || `student_index` || `student_index -> mentor_index` ||
     223|| `membership_stages` || `ms_id`, `ms_name` || both left-hand sides are candidate keys ||
     224|| `membership_stage_records` || `msr_id` || the key determines all non-primary attributes ||
     225|| `organizational_functions` || `of_id`, `of_title` || both left-hand sides are candidate keys ||
     226|| `board`, `non_board` || `of_id` || no non-trivial functional dependency has a non-key left-hand side ||
     227|| `function_mandates` || `fm_id` || the key determines all non-primary attributes ||
     228|| `activity_types` || `at_id`, `at_name` || both left-hand sides are candidate keys ||
     229|| `locations` || `l_id`, `l_name` || both left-hand sides are candidate keys ||
     230|| `activity_sessions`, `related_to` || `as_id` || the key determines the remaining attributes ||
     231|| `event_types` || `et_id`, `et_name` || both left-hand sides are candidate keys ||
     232|| `event_editions` || `ee_id` || the key determines all non-primary attributes ||
     233|| `event_edition_locations` || `(ee_id, l_id)` || no non-trivial functional dependency has a non-key left-hand side ||
     234|| `event_session_types` || `est_id`, `est_name` || both left-hand sides are candidate keys ||
     235|| `event_function_types` || `eft_id`, `eft_name` || both left-hand sides are candidate keys ||
     236|| `event_sessions` || `(ee_id, es_no)` || the key determines all non-primary attributes ||
     237|| `event_functions` || `(ee_id, ef_no)` || the key determines `eft_id` ||
     238|| `applications` || `application_id` || the key determines all non-primary attributes ||
     239|| `holds_event_function` || `(student_index, ee_id, ef_no)` || no non-trivial functional dependency has a non-key left-hand side ||
     240|| `participation`, `required_attendance`, `announces_absence`, `responsible_for` || `(student_index, as_id)` || every non-trivial dependency has the complete key on the left-hand side ||
     241|| `volunteers` || `(student_index, ee_id, es_no)` || the key determines `volunteer_role` ||
     242|| `companies` || `c_id` || the key determines the company attributes ||
     243|| `cooperation` || `(c_id, ee_id)` || the key determines `cooperation_type` ||
     244
     245For every non-trivial dependency in these relations, the determinant is one of the candidate keys shown in the table. None of the 32 relations has a BCNF violation, so BCNF is the highest normal form reached by the decomposition.
     246
     247=== Non-additivity (loss-less decomposition) and validity of the functional dependencies ===
     248
     249For every binary FD-based decomposition step `R -> R1, R2`:
     250
     251{{{
     252R1 intersect R2 = X
     253X -> R1
     254}}}
     255
     256where `X` is the determinant used for that step. Therefore every binary step is loss-less.
     257
     258Example:
     259
     260{{{
     261ms_id -> ms_name
     262
     263R1 = membership_stages(ms_id, ms_name)
     264R2 = membership_stage_records(msr_id, student_index, ms_id, valid_from, valid_to)
     265
     266R1 intersect R2 = {ms_id}
     267ms_id -> R1
     268}}}
     269
     270The preservation of the initial functional dependencies was checked separately against the final relations:
     271
     272|| Dependencies from `Fc` || Final relation || Count ||
     273|| `student_index -> first_name, last_name, faculty, field_of_studies, year_of_studies, birthday, email, phone_number` || `students` || 8 ||
     274|| `student_index -> mentor_index` || `young_members` || 1 ||
     275|| `ms_id -> ms_name`; `ms_name -> ms_id` || `membership_stages` || 2 ||
     276|| `msr_id -> student_index, ms_id, valid_from, valid_to` || `membership_stage_records` || 4 ||
     277|| `of_id -> of_title`; `of_title -> of_id` || `organizational_functions` || 2 ||
     278|| `fm_id -> student_index, of_id, mandate_year` || `function_mandates` || 3 ||
     279|| `at_id -> at_name, at_description`; `at_name -> at_id` || `activity_types` || 3 ||
     280|| `l_id -> l_name`; `l_name -> l_id` || `locations` || 2 ||
     281|| `et_id -> et_name, et_description`; `et_name -> et_id` || `event_types` || 3 ||
     282|| `est_id -> est_name, est_description`; `est_name -> est_id` || `event_session_types` || 3 ||
     283|| `eft_id -> eft_name`; `eft_name -> eft_id` || `event_function_types` || 2 ||
     284|| `as_id -> at_id, l_id, as_start_time` || `activity_sessions` || 3 ||
     285|| `as_id -> ee_id` || `related_to` || 1 ||
     286|| `ee_id -> et_id, ee_title, ee_start_time, ee_end_time` || `event_editions` || 4 ||
     287|| `(ee_id, es_no) -> est_id, l_id, es_start_time, es_title, needed_no_volunteers` || `event_sessions` || 5 ||
     288|| `(ee_id, ef_no) -> eft_id` || `event_functions` || 1 ||
     289|| `application_id -> student_index, ee_id, ef_no, motivational_letter, application_type, application_status` || `applications` || 6 ||
     290|| `(student_index, as_id) -> rsvp_status, rsvp_at, attendance_status` || `participation` || 3 ||
     291|| `(student_index, as_id) -> reason, announced_at` || `announces_absence` || 2 ||
     292|| `(student_index, ee_id, es_no) -> volunteer_role` || `volunteers` || 1 ||
     293|| `c_id -> c_name, naframa_reference` || `companies` || 2 ||
     294|| `(c_id, ee_id) -> cooperation_type` || `cooperation` || 1 ||
     295|| '''Total''' || || '''62/62''' ||
     296
     297All 62 dependencies from `Fc` can therefore be enforced within individual final relations. Together with the loss-less check for every binary decomposition step, this shows that the decomposition both preserves the functional dependencies and has the loss-less join property.
     298
     299== Final result and discussion ==
     300
     301=== Normalized relational model ===
     302
     303The final normalized model contains the following relations:
     304
     305{{{
     306students(student_index, first_name, last_name, faculty, field_of_studies,
     307         year_of_studies, birthday, email, phone_number)
     308members(student_index)
     309observers(student_index)
     310young_members(student_index, mentor_index)
     311full_members(student_index)
     312alumni(student_index)
     313
     314membership_stages(ms_id, ms_name)
     315membership_stage_records(msr_id, student_index, ms_id, valid_from, valid_to)
     316
     317organizational_functions(of_id, of_title)
     318board(of_id)
     319non_board(of_id)
     320function_mandates(fm_id, student_index, of_id, mandate_year)
     321
     322activity_types(at_id, at_name, at_description)
     323locations(l_id, l_name)
     324activity_sessions(as_id, at_id, l_id, as_start_time)
     325related_to(as_id, ee_id)
     326
     327event_types(et_id, et_name, et_description)
     328event_editions(ee_id, et_id, ee_title, ee_start_time, ee_end_time)
     329event_edition_locations(ee_id, l_id)
     330event_session_types(est_id, est_name, est_description)
     331event_function_types(eft_id, eft_name)
     332event_sessions(ee_id, es_no, est_id, l_id, es_start_time, es_title,
     333               needed_no_volunteers)
     334event_functions(ee_id, ef_no, eft_id)
     335
     336applications(application_id, student_index, ee_id, ef_no,
     337             motivational_letter, application_type, application_status)
     338holds_event_function(student_index, ee_id, ef_no)
     339
     340participation(student_index, as_id, rsvp_status, rsvp_at, attendance_status)
     341required_attendance(student_index, as_id)
     342announces_absence(student_index, as_id, reason, announced_at)
     343responsible_for(student_index, as_id)
     344volunteers(student_index, ee_id, es_no, volunteer_role)
     345
     346companies(c_id, c_name, naframa_reference)
     347cooperation(c_id, ee_id, cooperation_type)
     348}}}
     349
     350=== Discussion ===
     351
     352The normalized model obtained independently in this phase has the same relations, attributes and keys as the design documented in RelationalDesign. The relations created from the ER model already separate students, reusable types, locations, concrete sessions, event editions, applications and M:N relationships in the same way required by the normalization procedure.
     353
     354No relation from the Phase P2 design needs to be changed. The relational design from RelationalDesign will continue to be used for the following project phases.
     355
     356== AI Use ==
     357
     358AI was used during this phase as a consultation, drafting and checking tool while preparing the normalization from the completed ER model and relational design. The AI-assisted parts were reviewed against the project requirements and course material before being included.
     359
     360Full AI usage documentation: NormalizationAIUsage.