Changes between Version 4 and Version 5 of Normalization


Ignore:
Timestamp:
05/28/26 02:59:30 (7 hours ago)
Author:
181201
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v4 v5  
    5151'''FD10:''' {{{payment_id}}} → {{{amount}}}, {{{payment_type}}}, {{{booking_id}}}
    5252
     53'''FD11:''' ({{{admin_id}}}, {{{user_id}}}) → ∅ (represents AdminManagement M:N)
     54
     55'''FD12:''' ({{{booking_id}}}, {{{pet_id}}}) → ∅ (represents BookingPets M:N)
     56
     57'''FD13:''' ({{{sitter_id}}}, {{{service_id}}}) → ∅ (represents SitterServices M:N)
     58
     59'''FD14:''' ({{{booking_id}}}, {{{service_id}}}) → ∅ (represents BookingServices M:N)
     60
    5361== Candidate keys and primary key selection ==
    5462
    55 === Formally identify candidate keys ===
    56 To determine a candidate key of the universal de-normalized relation '''R''', we must find a minimal set of attributes whose closure (K+) determines all other attributes in the relation.
    57 
    58 Because there are independent M:N relationships and disjoint entities that do not functionally determine each other, the candidate key must be a composite of the independent determinants.
    59 
    60 '''Candidate Key K = {''' {{{admin_id}}}, {{{owner_id}}}, {{{sitter_id}}}, {{{pet_id}}}, {{{service_id}}}, {{{booking_id}}}, {{{review_id}}}, {{{payment_id}}}'''}'''
    61 
    62 
    63 === Closure Proof for K ===
    64 Let K = { admin_id, owner_id, sitter_id, pet_id, service_id, booking_id, review_id, payment_id }
    65 
    66 Compute K+:
    67  * '''Start:''' K+ = K
    68  * '''From FD2:''' admin_id -> user_id
    69    * Add: user_id
    70  * '''From FD1:''' user_id -> username, first_name, last_name, password, email
    71    * Add: username, first_name, last_name, password, email
    72  * '''From FD3 & FD4:''' owner_id -> user_id and sitter_id -> user_id
    73    * (user_id already belongs to K+)
    74  * '''From FD6:''' pet_id -> pet_name, photo, age, special_needs, pet_description, owner_id, pettype_id
    75    * Add: pet_name, photo, age, special_needs, pet_description, pettype_id
    76    * (owner_id already belongs to K+)
    77  * '''From FD5:''' pettype_id -> species, average_lifespan, needs_outdoor_walk
    78    * Add: species, average_lifespan, needs_outdoor_walk
    79  * '''From FD7:''' service_id -> service_type, service_description
    80    * Add: service_type, service_description
    81  * '''From FD8:''' booking_id -> booking_status, date_from, date_to, address, owner_id, sitter_id
    82    * Add: booking_status, date_from, date_to, address
    83    * (owner_id and sitter_id already belong to K+)
    84  * '''From FD9:''' review_id -> rating, comment, booking_id
    85    * Add: rating, comment
    86    * (booking_id already belongs to K+)
    87  * '''From FD10:''' payment_id -> amount, payment_type, booking_id
    88    * Add: amount, payment_type
    89    * (booking_id already belongs to K+)
    90 
    91 Therefore, '''K+ = R''', so K is a valid superkey.
    92 
    93 K is '''minimal'''. If we remove any single attribute from K (such as removing service_id or pet_id), we entirely lose our starting point for that independent element, so its specific attributes could never be used to the closure. Which means, K is an official Candidate Key.
    94 
    95 === Primary Key Selection ===
    96 We select the single composite candidate key K as the official primary key of the initial de-normalized relation:
    97 
    98 {{{admin_id, owner_id, sitter_id, pet_id, service_id, booking_id, review_id, payment_id}}}
    99 === Primary Key Selection ===
    100 We select the candidate key '''K''' as the primary key of the initial de-normalized relation.
     63=== Determination of Candidate Keys ===
     64To find a candidate key, we must find a minimal set of attributes whose closure contains all attributes of the relation. We begin by classifying all attributes based on where they appear in the Functional Dependencies.
     65
     66=== Attribute Classification (Left / Right Side) ===
     67|| '''Attribute''' || '''Left Side''' || '''Right Side''' || '''Classification''' ||
     68|| '''admin_id''' || ✓ (FD2, FD11) || ✗ || '''Left only''' ||
     69|| '''pet_id''' || ✓ (FD6, FD12) || ✗ || '''Left only''' ||
     70|| '''service_id''' || ✓ (FD7, FD13, FD14) || ✗ || '''Left only''' ||
     71|| '''review_id''' || ✓ (FD9) || ✗ || '''Left only''' ||
     72|| '''payment_id''' || ✓ (FD10) || ✗ || '''Left only''' ||
     73|| {{{user_id}}} || ✓ (FD1, FD11) || ✓ (FD2, FD3, FD4) || Both ||
     74|| {{{owner_id}}} || ✓ (FD3) || ✓ (FD6, FD8) || Both ||
     75|| {{{sitter_id}}} || ✓ (FD4, FD13) || ✓ (FD8) || Both ||
     76|| {{{pettype_id}}} || ✓ (FD5) || ✓ (FD6) || Both ||
     77|| {{{booking_id}}} || ✓ (FD8, FD12, FD14) || ✓ (FD9, FD10) || Both ||
     78|| {{{username}}}, {{{first_name}}}, {{{last_name}}}, {{{password}}}, {{{email}}} || ✗ || ✓ (FD1) || Right only ||
     79|| {{{species}}}, {{{average_lifespan}}}, {{{needs_outdoor_walk}}} || ✗ || ✓ (FD5) || Right only ||
     80|| {{{pet_name}}}, {{{photo}}}, {{{age}}}, {{{special_needs}}}, {{{pet_description}}} || ✗ || ✓ (FD6) || Right only ||
     81|| {{{service_type}}}, {{{service_description}}} || ✗ || ✓ (FD7) || Right only ||
     82|| {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}} || ✗ || ✓ (FD8) || Right only ||
     83|| {{{rating}}}, {{{comment}}} || ✗ || ✓ (FD9) || Right only ||
     84|| {{{amount}}}, {{{payment_type}}} || ✗ || ✓ (FD10) || Right only ||
     85
     86=== Attributes That Appear ONLY on the Left Side ===
     87According to relational theory, attributes that appear ''only'' on the left side of functional dependencies can never be derived from any other attribute. Therefore, they '''must''' be part of every candidate key:
     88 * '''admin_id'''
     89 * '''pet_id'''
     90 * '''service_id'''
     91 * '''review_id'''
     92 * '''payment_id'''
     93
     94=== 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}⁺ }}}:
     98 * '''From FD2''' ({{{admin_id}}} → {{{user_id}}}): We obtain {{{user_id}}}
     99 * '''From FD1''' ({{{user_id}}} → {{{username}}}, {{{first_name}}}...): We obtain {{{username, first_name, last_name, password, email}}}
     100 * '''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 * '''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 * '''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}}}
     105 * '''From FD10''' ({{{payment_id}}} → {{{amount}}}, {{{payment_type}}}, {{{booking_id}}}): We obtain {{{amount, payment_type}}} ({{{booking_id}}} is already in closure)
     106 * '''From FD3 & FD4:''' {{{owner_id}}} and {{{sitter_id}}} map to {{{user_id}}}, which is already in the closure.
     107 * '''From FD11-FD14:''' All composite pairings (e.g., {{{booking_id}}} and {{{pet_id}}}) are already present in the closure, satisfying the M:N relations.
     108
     109'''Closure = Universal_Relation ✓''' (all 33 attributes are successfully derived)
     110
     111=== Minimality Check ===
     112To formally prove this key is minimal, we test proper subsets of '''K = {admin_id, pet_id, service_id, review_id, payment_id}''':
     113
     114|| '''Subset''' || '''Closure Equals Universal_Relation?''' || '''Justification''' ||
     115|| '''K − {admin_id}''' || ✗ NO || Cannot derive {{{admin_id}}}. ||
     116|| '''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|| '''K − {review_id}''' || ✗ NO || Cannot derive review attributes ({{{review_id, rating, comment}}}). ||
     119|| '''K − {payment_id}''' || ✗ NO || Cannot derive payment attributes ({{{payment_id, amount, payment_type}}}). ||
     120
     121'''Conclusion:''' K = {admin_id, pet_id, service_id, review_id, payment_id} is minimal and is the strictly mathematically correct candidate key.
     122
     123=== 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.
    101127
    102128=== Current Normal Form Status ===
     
    105131== Step-by-step decomposition to highest possible normal form ==
    106132
    107 === Step 1: Decomposition to 2NF ===
     133=== 1. Decomposition to 2NF ===
    108134
    109135'''Relation analyzed:''' The universal de-normalized relation '''R'''.
     
    143169'''BookingServices''' ({{{booking_id}}}, {{{service_id}}})
    144170
    145 '''Validation:'''
    146 
    147 ''Loss-less join property:'' Preserved. Every split was made along a functional dependency where the common attribute became a candidate key in the new relation.
    148 
    149 ''Dependency preservation:'' Preserved. Every functional dependency (FD1 through FD10) is fully contained within a single decomposed table.
     171'''Validation of 2NF Decomposition:'''
     172
     173'''1. Loss-less Join Property:'''
     174By definition (Heath's Theorem), a decomposition of relation ''R'' into ''R1'' and ''R2'' is lossless if the common attributes (''R1'' ∩ ''R2'') form a superkey for either ''R1'' or ''R2''.
     175Our 14 relations were not created in a single split, but through '''successive binary decompositions'''.
     176 * For example, in the first step, ''R'' was decomposed into ''R_Users'' and ''R_Remainder'' based on FD1. The intersection of these two relations is {{{user_id}}}. Because {{{user_id}}} is the primary key of ''R_Users'', the functional dependency {{{user_id → username, first_name, last_name, password, email}}} is preserved, proving this specific binary split is lossless.
     177 * In another step, the remainder was split into ''R_Pets'' and a new remainder based on FD6. The intersection is {{{pet_id}}}. Since {{{pet_id}}} is the primary key of ''R_Pets'', this split is also lossless.
     178 * By recursively applying this exact binary splitting logic along the boundaries of FD2 through FD14, every single decomposition step shared a primary key with the remainder relation. Therefore, the final 14-table schema is strictly lossless.
     179
     180'''2. Dependency Preservation:'''
     181A 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 FD14).
     182Because we explicitly created our relations based on the exact determinants of our FDs, every single functional dependency is fully localized within a single table.
     183 * 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.
     184 * Similarly, FD7 ({{{service_id → service_type, service_description}}}) is entirely contained within the '''Services''' table.
     185Since all 14 original FDs are preserved natively inside the 14 new relations, the decomposition is strictly dependency preserving.
    150186
    151187=== Step 2: Decomposition to 3NF ===
     
    153189'''Relations analyzed:''' All 14 relations obtained from the 2NF decomposition.
    154190
    155 '''Issues with higher normal forms:''' A relation violates 3NF if there is a transitive dependency (A → B → C) where a non-prime attribute depends on another non-prime attribute.
    156 
    157 '''Action taken:''' We inspect the 2NF relations for transitive dependencies.
    158 
    159 In '''Bookings''', {{{booking_id}}} determines {{{owner_id}}}, and globally {{{owner_id}}} determines {{{user_id}}} details. However, the user details are NOT stored inside Bookings; they are safely isolated in the '''Users''' table.
    160 
    161 In '''Reviews''', {{{review_id}}} determines {{{booking_id}}}, which globally determines the Sitter. However, sitter details are not stored inside the Reviews table.
    162 
    163 '''Result:''' Because we did not store redundant foreign keys (like putting {{{sitter_id}}} inside the Reviews table), there are absolutely no transitive dependencies within the non-prime attributes of any relation.
    164 
    165 '''Status:''' All relations are already in '''3NF'''.
    166 
    167 === Step 3: Decomposition to BCNF ===
     191'''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.
     192
     193'''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.
     194
     195* '''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.
     196* '''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.
     197* '''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.
     198* '''In Junction Tables (BookingPets, AdminManagement):''' These relations consist purely of composite primary keys with zero non-prime attributes, automatically satisfying 3NF.
     199
     200'''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.
     201
     202'''Status:''' All 14 relations naturally satisfy '''3NF'''.
     203=== 3. Decomposition to BCNF ===
    168204
    169205'''Relations analyzed:''' All 14 relations currently in 3NF.
     
    204240
    205241'''Status:''' All 14 relations naturally satisfy '''BCNF'''. The decomposition process is complete.
     242
    206243== Final result and discussion ==
    207244