| 3 | | This page documents the relational design for BEST Skopje Hub, based on !ERModel_v09. The design uses partial transformation from the ER model into a PostgreSQL relational schema. Strong entities are mapped directly to relations, weak entities include the primary keys of their owner entities, specializations are mapped with one relation for the supertype and one relation for each subtype, and M:N relationships are mapped as separate relations. |
| 4 | | |
| 5 | | Some attribute names were adapted to SQL-friendly snake_case names. For example, the ER attribute `index` is represented as `student_index`, and the !EventEditions attributes `title`, `start`, and `end` are represented as `event_title`, `event_start_time`, and `event_end_time`. |
| | 3 | This page documents the relational design for BEST Skopje Hub, based on !ERModel_v10. The design uses partial transformation from the ER model into a PostgreSQL relational schema. Strong entities are mapped directly to relations, weak entities include the primary keys of their owner entities, specializations are mapped with one relation for the supertype and one relation for each subtype, and M:N relationships are mapped as separate relations. |
| 53 | | student_index, ms_name, valid_from, valid_to, |
| 54 | | PK(student_index, ms_name, valid_from), |
| 55 | | FK(student_index) -> members(student_index), |
| 56 | | FK(ms_name) -> membership_stages(ms_name) |
| | 52 | student_index, ms_id, valid_from, valid_to, |
| | 53 | PK(student_index, ms_id, valid_from), |
| | 54 | FK(student_index) -> members(student_index), |
| | 55 | FK(ms_id) -> membership_stages(ms_id) |
| 71 | | of_title, |
| 72 | | PK(of_title), |
| 73 | | FK(of_title) -> organizational_functions(of_title) |
| 74 | | ) |
| 75 | | |
| 76 | | is_organizational_function( |
| 77 | | student_index, of_title, mandate, |
| 78 | | PK(student_index, of_title, mandate), |
| | 71 | of_id, |
| | 72 | PK(of_id), |
| | 73 | FK(of_id) -> organizational_functions(of_id) |
| | 74 | ) |
| | 75 | |
| | 76 | function_mandates( |
| | 77 | student_index, of_id, mandate_year, |
| | 78 | PK(student_index, of_id, mandate_year), |
| 89 | | at_name, as_start_time, as_location, |
| 90 | | PK(at_name, as_start_time, as_location), |
| 91 | | FK(at_name) -> activity_types(at_name) |
| | 96 | as_id, at_id, l_id, as_start_time, |
| | 97 | PK(as_id), |
| | 98 | FK(at_id) -> activity_types(at_id), |
| | 99 | FK(l_id) -> locations(l_id) |
| 95 | | at_name, as_start_time, as_location, et_name, event_title, event_start_time, |
| 96 | | PK(at_name, as_start_time, as_location), |
| 97 | | FK(at_name, as_start_time, as_location) -> activity_sessions(at_name, as_start_time, as_location), |
| 98 | | FK(et_name, event_title, event_start_time) -> event_editions(et_name, event_title, event_start_time) |
| | 103 | as_id, ee_id, |
| | 104 | PK(as_id), |
| | 105 | FK(as_id) -> activity_sessions(as_id), |
| | 106 | FK(ee_id) -> event_editions(ee_id) |
| 107 | | et_name, event_title, event_start_time, event_end_time, |
| 108 | | PK(et_name, event_title, event_start_time), |
| 109 | | FK(et_name) -> event_types(et_name) |
| | 116 | ee_id, et_id, ee_title, ee_start_time, ee_end_time, |
| | 117 | PK(ee_id), |
| | 118 | FK(et_id) -> event_types(et_id) |
| 113 | | et_name, event_title, event_start_time, location, |
| 114 | | PK(et_name, event_title, event_start_time, location), |
| 115 | | FK(et_name, event_title, event_start_time) -> event_editions(et_name, event_title, event_start_time) |
| | 122 | ee_id, l_id, |
| | 123 | PK(ee_id, l_id), |
| | 124 | FK(ee_id) -> event_editions(ee_id), |
| | 125 | FK(l_id) -> locations(l_id) |
| 124 | | et_name, event_title, event_start_time, est_name, es_start_time, location, es_title, |
| 125 | | PK(et_name, event_title, event_start_time, est_name, es_start_time, location), |
| 126 | | FK(et_name, event_title, event_start_time) -> event_editions(et_name, event_title, event_start_time), |
| 127 | | FK(est_name) -> event_session_types(est_name) |
| 128 | | ) |
| 129 | | |
| 130 | | core_team_functions( |
| 131 | | et_name, event_title, event_start_time, function_name, |
| 132 | | PK(et_name, event_title, event_start_time, function_name), |
| 133 | | FK(et_name, event_title, event_start_time) -> event_editions(et_name, event_title, event_start_time) |
| | 135 | ee_id, es_no, est_id, l_id, es_start_time, es_title, needed_no_volunteers, |
| | 136 | PK(ee_id, es_no), |
| | 137 | FK(ee_id) -> event_editions(ee_id), |
| | 138 | FK(est_id) -> event_session_types(est_id), |
| | 139 | FK(l_id) -> locations(l_id) |
| | 140 | ) |
| | 141 | |
| | 142 | event_functions( |
| | 143 | ee_id, ef_no, ef_name, |
| | 144 | PK(ee_id, ef_no), |
| | 145 | FK(ee_id) -> event_editions(ee_id) |
| 137 | | application_id, student_index, et_name, event_title, event_start_time, |
| 138 | | function_name, motivational_letter, application_type, application_status, |
| | 149 | application_id, student_index, ee_id, ef_no, |
| | 150 | motivational_letter, application_type, application_status, |
| 141 | | FK(et_name, event_title, event_start_time) -> event_editions(et_name, event_title, event_start_time), |
| 142 | | FK(et_name, event_title, event_start_time, function_name) -> core_team_functions(et_name, event_title, event_start_time, function_name) |
| | 153 | FK(ee_id) -> event_editions(ee_id), |
| | 154 | FK(ee_id, ef_no) -> event_functions(ee_id, ef_no) |
| 146 | | student_index, at_name, as_start_time, as_location, |
| 147 | | rsvp_status, rsvp_at, attendance_status, |
| 148 | | PK(student_index, at_name, as_start_time, as_location), |
| | 158 | student_index, as_id, rsvp_status, rsvp_at, attendance_status, |
| | 159 | PK(student_index, as_id), |
| 154 | | student_index, at_name, as_start_time, as_location, reason, announced_at, |
| 155 | | PK(student_index, at_name, as_start_time, as_location), |
| 156 | | FK(student_index) -> members(student_index), |
| 157 | | FK(at_name, as_start_time, as_location) -> activity_sessions(at_name, as_start_time, as_location) |
| | 165 | student_index, as_id, reason, announced_at, |
| | 166 | PK(student_index, as_id), |
| | 167 | FK(student_index) -> members(student_index), |
| | 168 | FK(as_id) -> activity_sessions(as_id) |
| 161 | | student_index, at_name, as_start_time, as_location, |
| 162 | | PK(student_index, at_name, as_start_time, as_location), |
| 163 | | FK(student_index) -> members(student_index), |
| 164 | | FK(at_name, as_start_time, as_location) -> activity_sessions(at_name, as_start_time, as_location) |
| | 172 | student_index, as_id, |
| | 173 | PK(student_index, as_id), |
| | 174 | FK(student_index) -> members(student_index), |
| | 175 | FK(as_id) -> activity_sessions(as_id) |
| 168 | | student_index, et_name, event_title, event_start_time, |
| 169 | | est_name, es_start_time, location, volunteer_role, |
| 170 | | PK(student_index, et_name, event_title, event_start_time, est_name, es_start_time, location), |
| 171 | | FK(student_index) -> members(student_index), |
| 172 | | FK(et_name, event_title, event_start_time, est_name, es_start_time, location) -> event_sessions(et_name, event_title, event_start_time, est_name, es_start_time, location) |
| | 179 | student_index, ee_id, es_no, volunteer_role, |
| | 180 | PK(student_index, ee_id, es_no), |
| | 181 | FK(student_index) -> members(student_index), |
| | 182 | FK(ee_id, es_no) -> event_sessions(ee_id, es_no) |
| 194 | | The weak entities from the ER model are represented using composite primary keys. `activity_sessions` includes the key of `activity_types`. `event_editions` includes the key of `event_types`. `event_sessions` includes the composite key of `event_editions`, the key of `event_session_types`, and its partial key attributes `es_start_time` and `location`. `core_team_functions` includes the composite key of `event_editions` and its partial key `function_name`. |
| 195 | | |
| 196 | | The multivalued `locations` attribute of !EventEditions is transformed into the separate relation `event_edition_locations`. |
| 197 | | |
| 198 | | The relationships `has_stage`, `participation`, `announces_absence`, `responsible_for`, `volunteers`, `cooperation`, `related_to`, and `is` are represented as relations because they either have M:N cardinality, their own attributes, or are clearer without nullable foreign-key columns. The relationship `related_to` is represented separately because only some activity sessions are connected to event editions. The relationship `applies_with` is represented with the foreign key `student_index` in `applications`, because each application belongs to one student. The N:1 relationships `for_function`, `for_participation`, and `mentorship` are represented directly with foreign keys on the N-side relation. |
| | 204 | The weak entities from !ERModel_v10 are represented with composite primary keys where they still depend on an owner entity. `event_functions` uses `(ee_id, ef_no)`, and `event_sessions` uses `(ee_id, es_no)`. Other concrete entities such as `activity_sessions` and `event_editions` use their own numeric identifiers. |
| | 205 | |
| | 206 | The Locations entity is represented with `locations`. The relationship between !EventEditions and Locations is represented with `event_edition_locations`. |
| | 207 | |
| | 208 | The relationships `has_stage`, `participation`, `announces_absence`, `responsible_for`, `volunteers`, `cooperation`, `related_to`, `holds_function`, and the event-edition location relationship are represented as relations because they either have M:N cardinality, their own attributes, or are clearer without nullable foreign-key columns. The relationship `related_to` is represented separately because only some activity sessions are connected to event editions. The relationship `applies_with` is represented with the foreign key `student_index` in `applications`, because each application belongs to one student. The N:1 relationships `for_function`, `for_participation`, `takes_place_at`, `held_at`, and `mentorship` are represented directly with foreign keys on the N-side relation. |