Changes between Version 8 and Version 9 of Normalization
- Timestamp:
- 08/28/26 00:09:01 (5 days ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Normalization
v8 v9 45 45 '''FD7:''' {{{service_id}}} → {{{service_type}}}, {{{service_description}}} 46 46 47 '''FD8:''' {{{booking_id}}} → {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}} 47 '''FD8:''' {{{booking_id}}} → {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}}, {{{service_id}}} 48 48 49 49 '''FD9:''' {{{review_id}}} → {{{rating}}}, {{{comment}}}, {{{booking_id}}} … … 56 56 57 57 '''FD13:''' ({{{sitter_id}}}, {{{service_id}}}) → ∅ (represents SitterServices M:N) 58 59 '''FD14:''' ({{{booking_id}}}, {{{service_id}}}) → ∅ (represents BookingServices M:N)60 58 61 59 == Candidate keys and primary key selection == … … 68 66 || '''admin_id''' || ✓ (FD2, FD11) || ✗ || '''Left only''' || 69 67 || '''pet_id''' || ✓ (FD6, FD12) || ✗ || '''Left only''' || 70 || '''service_id''' || ✓ (FD7, FD13, FD14) || ✗ || '''Left only''' ||71 68 || '''review_id''' || ✓ (FD9) || ✗ || '''Left only''' || 72 69 || '''payment_id''' || ✓ (FD10) || ✗ || '''Left only''' || … … 74 71 || {{{owner_id}}} || ✓ (FD3) || ✓ (FD6, FD8) || Both || 75 72 || {{{sitter_id}}} || ✓ (FD4, FD13) || ✓ (FD8) || Both || 73 || {{{service_id}}} || ✓ (FD7, FD13) || ✓ (FD8) || Both || 76 74 || {{{pettype_id}}} || ✓ (FD5) || ✓ (FD6) || Both || 77 || {{{booking_id}}} || ✓ (FD8, FD12 , FD14) || ✓ (FD9, FD10) || Both ||75 || {{{booking_id}}} || ✓ (FD8, FD12) || ✓ (FD9, FD10) || Both || 78 76 || {{{username}}}, {{{first_name}}}, {{{last_name}}}, {{{password}}}, {{{email}}} || ✗ || ✓ (FD1) || Right only || 79 77 || {{{species}}}, {{{average_lifespan}}}, {{{needs_outdoor_walk}}} || ✗ || ✓ (FD5) || Right only || … … 88 86 * '''admin_id''' 89 87 * '''pet_id''' 90 * '''service_id'''91 88 * '''review_id''' 92 89 * '''payment_id''' 93 90 94 91 === Closure Computation === 95 '''Step 1:''' We start with our mandatory attributes {{{ {admin_id, pet_id, service_id,review_id, payment_id} }}} and compute the mathematical closure:96 97 {{{ {admin_id, pet_id, service_id,review_id, payment_id}⁺ }}}:92 '''Step 1:''' We start with our mandatory attributes {{{ {admin_id, pet_id, review_id, payment_id} }}} and compute the mathematical closure: 93 94 {{{ {admin_id, pet_id, review_id, payment_id}⁺ }}}: 98 95 * '''From FD2''' ({{{admin_id}}} → {{{user_id}}}): We obtain {{{user_id}}} 99 96 * '''From FD1''' ({{{user_id}}} → {{{username}}}, {{{first_name}}}...): We obtain {{{username, first_name, last_name, password, email}}} 100 97 * '''From FD6''' ({{{pet_id}}} → {{{pet_name}}}, {{{photo}}}... {{{owner_id}}}, {{{pettype_id}}}): We obtain {{{pet_name, photo, age, special_needs, pet_description, owner_id, pettype_id}}} 101 98 * '''From FD5''' ({{{pettype_id}}} → {{{species}}}...): We obtain {{{species, average_lifespan, needs_outdoor_walk}}} 102 * '''From FD7''' ({{{service_id}}} → {{{service_type}}}...): We obtain {{{service_type, service_description}}}103 99 * '''From FD9''' ({{{review_id}}} → {{{rating}}}, {{{comment}}}, {{{booking_id}}}): We obtain {{{rating, comment, booking_id}}} 104 * '''From FD8''' ({{{booking_id}}} → {{{booking_status}}}... {{{sitter_id}}}): We obtain {{{booking_status, date_from, date_to, address, sitter_id}}} 100 * '''From FD8''' ({{{booking_id}}} → {{{booking_status}}}... {{{sitter_id}}}, {{{service_id}}}): We obtain {{{booking_status, date_from, date_to, address, sitter_id, service_id}}} 101 * '''From FD7''' ({{{service_id}}} → {{{service_type}}}, {{{service_description}}}): We obtain {{{service_type, service_description}}} 105 102 * '''From FD10''' ({{{payment_id}}} → {{{amount}}}, {{{payment_type}}}, {{{booking_id}}}): We obtain {{{amount, payment_type}}} ({{{booking_id}}} is already in closure) 106 103 * '''From FD3 & FD4:''' {{{owner_id}}} and {{{sitter_id}}} map to {{{user_id}}}, which is already in the closure. 107 * '''From FD11-FD1 4:''' All composite pairings (e.g., {{{booking_id}}} and {{{pet_id}}}) are already present in the closure, satisfying the M:N relations.104 * '''From FD11-FD13:''' All composite pairings (e.g., {{{booking_id}}} and {{{pet_id}}}) are already present in the closure, satisfying the M:N relations. 108 105 109 106 '''Closure = Universal_Relation ✓''' (all 33 attributes are successfully derived) 110 107 111 108 === Minimality Check === 112 To formally prove this key is minimal, we test proper subsets of '''K = {admin_id, pet_id, service_id,review_id, payment_id}''':109 To formally prove this key is minimal, we test proper subsets of '''K = {admin_id, pet_id, review_id, payment_id}''': 113 110 114 111 || '''Subset''' || '''Closure Equals Universal_Relation?''' || '''Justification''' || 115 112 || '''K − {admin_id}''' || ✗ NO || Cannot derive {{{admin_id}}}. || 116 113 || '''K − {pet_id}''' || ✗ NO || Cannot derive pet attributes ({{{pet_name, photo, age, special_needs, pet_description}}}). || 117 || '''K − {service_id}''' || ✗ NO || Cannot derive service attributes ({{{service_type, service_description}}}). ||118 114 || '''K − {review_id}''' || ✗ NO || Cannot derive review attributes ({{{review_id, rating, comment}}}). || 119 115 || '''K − {payment_id}''' || ✗ NO || Cannot derive payment attributes ({{{payment_id, amount, payment_type}}}). || 120 116 121 '''Conclusion:''' K = {admin_id, pet_id, service_id,review_id, payment_id} is minimal and is the strictly mathematically correct candidate key.117 '''Conclusion:''' K = {admin_id, pet_id, review_id, payment_id} is minimal and is the strictly mathematically correct candidate key. 122 118 123 119 === Choice of Primary Key === 124 '''Chosen Primary Key:''' {{{ {admin_id, pet_id, service_id,review_id, payment_id} }}}125 126 '''Justification:''' This composite key is the officially proven minimal Candidate Key. Attempting to include other logical identifiers (such as {{{owner_id}}}, {{{sitter_id}}}, or {{{booking_id}}}) would violate the rule of minimality, because the closure proof demonstrates those attributes are functionally dependent on the core transactional IDs.120 '''Chosen Primary Key:''' {{{ {admin_id, pet_id, review_id, payment_id} }}} 121 122 '''Justification:''' This composite key is the officially proven minimal Candidate Key. Attempting to include other logical identifiers (such as {{{owner_id}}}, {{{sitter_id}}}, {{{service_id}}} or {{{booking_id}}}) would violate the rule of minimality, because the closure proof demonstrates those attributes are functionally dependent on the core transactional IDs. In particular {{{service_id}}} is no longer part of the key, because each {{{Booking}}} requires exactly one {{{Service}}} and therefore {{{service_id}}} is derivable from {{{booking_id}}} through FD8. 127 123 128 124 === Current Normal Form Status === … … 155 151 '''Services''' ({{{service_id}}}, {{{service_type}}}, {{{service_description}}}) 156 152 157 '''Bookings''' ({{{booking_id}}}, {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}} )153 '''Bookings''' ({{{booking_id}}}, {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}}, {{{service_id}}}) 158 154 159 155 '''Reviews''' ({{{review_id}}}, {{{rating}}}, {{{comment}}}, {{{booking_id}}}) … … 167 163 '''SitterServices''' ({{{sitter_id}}}, {{{service_id}}}) 168 164 169 '''BookingServices''' ({{{booking_id}}}, {{{service_id}}})170 171 165 '''1. Loss-less Join Property Validation:''' 172 By definition (Heath's Theorem), a decomposition of relation ''R'' into ''R1'' and ''R2'' is lossless if the intersection of their attributes (''R1'' ∩ ''R2'') forms a superkey for either ''R1'' or ''R2''. To achieve our final schema without data loss, the universal relation ''R'' was decomposed through '''1 3successive binary splits'''. Below is the formal proof of each split, detailing the exact attributes partitioned.166 By definition (Heath's Theorem), a decomposition of relation ''R'' into ''R1'' and ''R2'' is lossless if the intersection of their attributes (''R1'' ∩ ''R2'') forms a superkey for either ''R1'' or ''R2''. To achieve our final schema without data loss, the universal relation ''R'' was decomposed through '''12 successive binary splits'''. Below is the formal proof of each split, detailing the exact attributes partitioned. 173 167 174 168 Let '''R_remainder''' be the remainder relation after each split … … 228 222 '''Split 8: Extracting Bookings (FD8)''' 229 223 * '''Decomposition:''' '''R_remainder7''' is split into '''Bookings''' and '''R_remainder8'''. 230 * '''Attributes in Bookings:''' {{{ {booking_id, booking_status, date_from, date_to, address, owner_id, sitter_id } }}}224 * '''Attributes in Bookings:''' {{{ {booking_id, booking_status, date_from, date_to, address, owner_id, sitter_id, service_id} }}} 231 225 * '''Attributes in R_remainder8:''' {{{ {admin_id, sitter_id, pet_id, service_id, booking_id, review_id, rating, comment, payment_id, amount, payment_type} }}} 232 226 * '''Intersection:''' '''Bookings''' ∩ '''R_remainder8''' = {{{ {booking_id} }}} … … 247 241 * '''Proof:''' {{{payment_id}}} is the Primary Key of the '''Payments''' table. The split is lossless. 248 242 249 '''Splits 11-1 3: Extracting M:N Relations/Junctions (FD11-FD14)'''243 '''Splits 11-12: Extracting M:N Relations/Junctions (FD11-FD13)''' 250 244 The final remainder relation ('''R_remainder10''') contains only the composite keys representing the Many-to-Many relationships: 251 245 * '''AdminManagement:''' {{{ {admin_id, user_id} }}} 252 246 * '''BookingPets:''' {{{ {booking_id, pet_id} }}} 253 247 * '''SitterServices:''' {{{ {sitter_id, service_id} }}} 254 * '''BookingServices:''' {{{ {booking_id, service_id} }}}255 248 256 249 Because these final tables consist only of their composite primary keys, any further binary separation will trivially satisfy Heath's Theorem. 257 250 258 '''Conclusion:''' Because every single step of the decomposition shared an intersection that was a guaranteed Primary Key, the final 1 4-table schema is strictly lossless.251 '''Conclusion:''' Because every single step of the decomposition shared an intersection that was a guaranteed Primary Key, the final 13-table schema is strictly lossless. 259 252 260 253 '''2. Dependency Preservation:''' 261 A decomposition is dependency preserving if the union of the functional dependencies in the new tables is equivalent to the original set of FDs (FD1 to FD1 4).254 A decomposition is dependency preserving if the union of the functional dependencies in the new tables is equivalent to the original set of FDs (FD1 to FD13). 262 255 Because we explicitly created our relations based on the exact determinants of our FDs, every single functional dependency is fully localized within a single table. 263 256 * For example, FD5 ({{{pettype_id → species, average_lifespan, needs_outdoor_walk}}}) can be completely verified within the new '''PetTypes''' table without needing to perform a JOIN operation with any other table. 264 257 * Similarly, FD7 ({{{service_id → service_type, service_description}}}) is entirely contained within the '''Services''' table. 265 Since all 14 original FDs are preserved natively inside the 14 new relations, the decomposition is strictly dependency preserving. 258 * FD8, which now also determines {{{service_id}}}, is entirely contained within the '''Bookings''' table, so the rule that a booking has exactly one service is verifiable without a JOIN. 259 Since all 13 original FDs are preserved natively inside the 13 new relations, the decomposition is strictly dependency preserving. 266 260 267 261 === Step 2: Decomposition to 3NF === 268 262 269 '''Relations analyzed:''' All 1 4relations obtained from the 2NF decomposition.263 '''Relations analyzed:''' All 13 relations obtained from the 2NF decomposition. 270 264 271 265 '''Issues with higher normal forms:''' A relation violates 3NF if there is a transitive dependency (A → B → C) where a non-prime attribute determines another non-prime attribute. … … 273 267 '''Action taken:''' We inspect the 2NF relations to ensure that all non-key attributes depend ''only'' on the primary key, and not on any other non-key attributes. We specifically target tables containing Foreign Keys, as this is where transitive chains can be present. 274 268 275 * '''In Bookings:''' While {{{booking_id}}} determines {{{owner_id}}}, we must check if {{{owner_id}}} (a non-prime attribute in this table) determines any other non-prime attributes ''within'' this table. It does not. The descriptive user details for the owner are safely isolated in the '''Users''' table.269 * '''In Bookings:''' While {{{booking_id}}} determines {{{owner_id}}}, {{{sitter_id}}} and {{{service_id}}}, we must check if any of these non-prime attributes determines another non-prime attribute ''within'' this table. They do not. The descriptive user details for the owner are safely isolated in the '''Users''' table, and the descriptive service details are safely isolated in the '''Services''' table. 276 270 * '''In Reviews:''' While {{{review_id}}} determines {{{booking_id}}}, we must check if {{{booking_id}}} (a non-prime attribute in this table) determines any other non-prime attributes ''within'' this table (such as the sitter's details). It does not. Those details are isolated in their respective tables. 277 271 * '''In Base Entities (Users, PetTypes, Services):''' All non-prime attributes logically depend directly on the primary key (example {{{species}}} depends only on {{{pettype_id}}}), making transitive chains mathematically impossible. … … 280 274 '''Result:''' Because we did not store redundant, descriptive data alongside our foreign keys, there are no instances where a non-prime attribute determines another non-prime attribute within the same relation. 281 275 282 '''Status:''' All 1 4relations naturally satisfy '''3NF'''.276 '''Status:''' All 13 relations naturally satisfy '''3NF'''. 283 277 284 278 === 3. Decomposition to BCNF === 285 279 286 '''Relations analyzed:''' All 1 4relations currently in 3NF.280 '''Relations analyzed:''' All 13 relations currently in 3NF. 287 281 288 282 '''Issues with higher normal forms:''' A relation violates Boyce-Codd Normal Form (BCNF) if a non-trivial functional dependency X → Y exists where X is not a superkey. 289 283 290 '''Action taken:''' We evaluate the left side (determinant) of every functional dependency within all 1 4relations:284 '''Action taken:''' We evaluate the left side (determinant) of every functional dependency within all 13 relations: 291 285 292 286 In '''Users''', {{{user_id}}} is a superkey. … … 316 310 In '''SitterServices''', the composite key ({{{sitter_id}}}, {{{service_id}}}) is the only determinant, meaning it is trivially a superkey. 317 311 318 In '''BookingServices''', the composite key ({{{booking_id}}}, {{{service_id}}}) is the only determinant, meaning it is trivially a superkey.319 320 312 '''Result:''' In every single relation, the determinant is a candidate/superkey. 321 313 322 '''Status:''' All 1 4relations naturally satisfy '''BCNF'''. The decomposition process is complete.314 '''Status:''' All 13 relations naturally satisfy '''BCNF'''. The decomposition process is complete. 323 315 324 316 == Final result and discussion == 325 317 326 318 === Final normalized relational design === 327 The final database schema operates in strict BCNF with the following 1 4relations:319 The final database schema operates in strict BCNF with the following 13 relations: 328 320 329 321 '''Users''' ({{{user_id}}}, {{{username}}}, {{{first_name}}}, {{{last_name}}}, {{{password}}}, {{{email}}}) … … 341 333 '''Services''' ({{{service_id}}}, {{{service_type}}}, {{{service_description}}}) 342 334 343 '''Bookings''' ({{{booking_id}}}, {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}} )335 '''Bookings''' ({{{booking_id}}}, {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}}, {{{service_id}}}) 344 336 345 337 '''Reviews''' ({{{review_id}}}, {{{rating}}}, {{{comment}}}, {{{booking_id}}}) … … 352 344 353 345 '''SitterServices''' ({{{sitter_id}}}, {{{service_id}}}) 354 355 '''BookingServices''' ({{{booking_id}}}, {{{service_id}}})356 346 357 347 === Discussion - compare with Phase 2 === 358 348 With completing the normalization process up to BCNF, we have proven that the resulting schema is identical to the logical design created in Phase 2. 349 350 == Version history == 351 352 [https://develop.finki.ukim.mk/projects/petsitter/wiki/Normalization_v01 v01] 353 * Initial version 354 355 [https://develop.finki.ukim.mk/projects/petsitter/wiki/Normalization v02] 356 * Current version, based on version [https://develop.finki.ukim.mk/projects/petsitter/wiki/ERModel v03] of the ER model 357 * Added {{{service_id}}} to the right side of '''FD8''', because {{{booking_id}}} now determines the single service of the booking 358 * Removed '''FD14''' ({{{booking_id}}}, {{{service_id}}}) → ∅, which represented the BookingServices M:N relation; now the number of functional dependencies is reduced from 14 to 13 359 * {{{service_id}}} is no longer an attribute that appears only on the left side, so the candidate key is reduced from {{{ {admin_id, pet_id, service_id, review_id, payment_id} }}} to {{{ {admin_id, pet_id, review_id, payment_id} }}} 360 * Added {{{service_id}}} to the '''Bookings''' relation and removed the '''BookingServices''' relation; the schema is reduced from 14 to 13 relations and the decomposition from 13 to 12 binary splits 361 * The 3NF and BCNF analysis is extended to cover the new {{{service_id}}} attribute in '''Bookings''' and the schema again satisfies BCNF
