| | 1 | = Normalization = |
| | 2 | |
| | 3 | == Initial de-normalized relation and functional dependencies == |
| | 4 | |
| | 5 | === Global set of attributes === |
| | 6 | Single unified de-normalized relation that includes all attributes from the ER model. It is important that there are no duplicate attribute names. |
| | 7 | |
| | 8 | '''R = {''' |
| | 9 | user_id, username, first_name, last_name, password, email, |
| | 10 | |
| | 11 | admin_id, |
| | 12 | |
| | 13 | owner_id, |
| | 14 | |
| | 15 | sitter_id, |
| | 16 | |
| | 17 | pettype_id, species, average_lifespan, needs_outdoor_walk, |
| | 18 | |
| | 19 | pet_id, pet_name, photo, age, special_needs, pet_description, |
| | 20 | |
| | 21 | service_id, service_type, service_description, |
| | 22 | |
| | 23 | booking_id, booking_status, date_from, date_to, address, |
| | 24 | |
| | 25 | review_id, rating, comment, |
| | 26 | |
| | 27 | payment_id, amount, payment_type |
| | 28 | |
| | 29 | '''}''' |
| | 30 | |
| | 31 | === Functional dependencies === |
| | 32 | |
| | 33 | '''FD1:''' {{{user_id}}} → {{{username}}}, {{{first_name}}}, {{{last_name}}}, {{{password}}}, {{{email}}} |
| | 34 | |
| | 35 | '''FD2:''' {{{admin_id}}} → {{{user_id}}} |
| | 36 | |
| | 37 | '''FD3:''' {{{owner_id}}} → {{{user_id}}} |
| | 38 | |
| | 39 | '''FD4:''' {{{sitter_id}}} → {{{user_id}}} |
| | 40 | |
| | 41 | '''FD5:''' {{{pettype_id}}} → {{{species}}}, {{{average_lifespan}}}, {{{needs_outdoor_walk}}} |
| | 42 | |
| | 43 | '''FD6:''' {{{pet_id}}} → {{{pet_name}}}, {{{photo}}}, {{{age}}}, {{{special_needs}}}, {{{pet_description}}}, {{{owner_id}}}, {{{pettype_id}}} |
| | 44 | |
| | 45 | '''FD7:''' {{{service_id}}} → {{{service_type}}}, {{{service_description}}} |
| | 46 | |
| | 47 | '''FD8:''' {{{booking_id}}} → {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}} |
| | 48 | |
| | 49 | '''FD9:''' {{{review_id}}} → {{{rating}}}, {{{comment}}}, {{{booking_id}}} |
| | 50 | |
| | 51 | '''FD10:''' {{{payment_id}}} → {{{amount}}}, {{{payment_type}}}, {{{booking_id}}} |
| | 52 | |
| | 53 | == Candidate keys and primary key selection == |
| | 54 | |
| | 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 = {''' {{{review_id}}}, {{{payment_id}}}, {{{pet_id}}}, {{{admin_id}}}, |
| | 61 | ({{{sitter_id}}}, {{{service_id}}}), |
| | 62 | ({{{booking_id}}}, {{{pet_id}}}), |
| | 63 | |
| | 64 | ({{{booking_id}}}, {{{service_id}}}), |
| | 65 | |
| | 66 | |
| | 67 | ({{{admin_id}}}, {{{user_id}}}) '''}''' |
| | 68 | |
| | 69 | '''Closure Proof:''' The closure of K (K+) includes every attribute in R because: |
| | 70 | |
| | 71 | {{{review_id}}} determines review attributes and {{{booking_id}}} (FD9). |
| | 72 | |
| | 73 | {{{booking_id}}} determines booking attributes, {{{owner_id}}}, and {{{sitter_id}}} (FD8). |
| | 74 | |
| | 75 | {{{owner_id}}} and {{{sitter_id}}} determine {{{user_id}}} (FD3, FD4), which determines all user attributes (FD1). |
| | 76 | |
| | 77 | {{{pet_id}}} determines pet attributes and {{{pettype_id}}} (FD6), which determines pet type attributes (FD5). |
| | 78 | |
| | 79 | Removing any attribute from K would result in losing an independent component of the database. Therefore, K is minimal and valid. |
| | 80 | |
| | 81 | === Primary Key Selection === |
| | 82 | We select the candidate key '''K''' as the primary key of the initial de-normalized relation. |
| | 83 | |
| | 84 | === Current Normal Form Status === |
| | 85 | Before decomposition, the universal relation '''R''' is in '''1NF'''. It satisfies 1NF because all attributes contain atomic values and there are no repeating groups. However, it violates 2NF due to severe partial dependencies on the composite primary key. |
| | 86 | |
| | 87 | == Step-by-step decomposition to highest possible normal form == |
| | 88 | |
| | 89 | === Step 1: Decomposition to 2NF === |
| | 90 | |
| | 91 | '''Relation analyzed:''' The universal de-normalized relation '''R'''. |
| | 92 | |
| | 93 | '''Issues with higher normal forms:''' R violates 2NF because non-prime attributes are partially dependent on components of the composite primary key. For example, {{{pet_name}}} depends ONLY on {{{pet_id}}}, not on the entire composite key '''K'''. |
| | 94 | |
| | 95 | '''Action taken:''' We decompose R into smaller relations by grouping attributes based on their exact determinants (eliminating partial dependencies). |
| | 96 | |
| | 97 | '''Relations obtained after 2NF decomposition:''' |
| | 98 | |
| | 99 | '''Users''' ({{{user_id}}}, {{{username}}}, {{{first_name}}}, {{{last_name}}}, {{{password}}}, {{{email}}}) |
| | 100 | |
| | 101 | '''Admins''' ({{{admin_id}}}, {{{user_id}}}) |
| | 102 | |
| | 103 | '''PetOwners''' ({{{owner_id}}}, {{{user_id}}}) |
| | 104 | |
| | 105 | '''PetSitters''' ({{{sitter_id}}}, {{{user_id}}}) |
| | 106 | |
| | 107 | '''PetTypes''' ({{{pettype_id}}}, {{{species}}}, {{{average_lifespan}}}, {{{needs_outdoor_walk}}}) |
| | 108 | |
| | 109 | '''Pets''' ({{{pet_id}}}, {{{pet_name}}}, {{{photo}}}, {{{age}}}, {{{special_needs}}}, {{{pet_description}}}, {{{owner_id}}}, {{{pettype_id}}}) |
| | 110 | |
| | 111 | '''Services''' ({{{service_id}}}, {{{service_type}}}, {{{service_description}}}) |
| | 112 | |
| | 113 | '''Bookings''' ({{{booking_id}}}, {{{booking_status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}}) |
| | 114 | |
| | 115 | '''Reviews''' ({{{review_id}}}, {{{rating}}}, {{{comment}}}, {{{booking_id}}}) |
| | 116 | |
| | 117 | '''Payments''' ({{{payment_id}}}, {{{amount}}}, {{{payment_type}}}, {{{booking_id}}}) |
| | 118 | |
| | 119 | '''AdminManagement''' ({{{admin_id}}}, {{{user_id}}}) |
| | 120 | |
| | 121 | '''BookingPets''' ({{{booking_id}}}, {{{pet_id}}}) |
| | 122 | |
| | 123 | '''SitterServices''' ({{{sitter_id}}}, {{{service_id}}}) |
| | 124 | |
| | 125 | '''BookingServices''' ({{{booking_id}}}, {{{service_id}}}) |
| | 126 | |
| | 127 | '''Validation:''' |
| | 128 | |
| | 129 | ''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. |
| | 130 | |
| | 131 | ''Dependency preservation:'' Preserved. Every functional dependency (FD1 through FD10) is fully contained within a single decomposed table. |
| | 132 | |
| | 133 | === Step 2: Decomposition to 3NF === |
| | 134 | |
| | 135 | '''Relations analyzed:''' All 14 relations obtained from the 2NF decomposition. |
| | 136 | |
| | 137 | '''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. |
| | 138 | |
| | 139 | '''Action taken:''' We inspect the 2NF relations for transitive dependencies. |
| | 140 | |
| | 141 | 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. |
| | 142 | |
| | 143 | In '''Reviews''', {{{review_id}}} determines {{{booking_id}}}, which globally determines the Sitter. However, sitter details are not stored inside the Reviews table. |
| | 144 | |
| | 145 | '''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. |
| | 146 | |
| | 147 | '''Status:''' All relations are already in '''3NF'''. |
| | 148 | |
| | 149 | === Step 3: Decomposition to BCNF === |
| | 150 | |
| | 151 | '''Relations analyzed:''' All 14 relations currently in 3NF. |
| | 152 | |
| | 153 | '''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. |
| | 154 | |
| | 155 | '''Action taken:''' We evaluate the left side (determinant) of every functional dependency within our relations. |
| | 156 | |
| | 157 | In '''Users''', {{{user_id}}} is a superkey. |
| | 158 | |
| | 159 | In '''Pets''', {{{pet_id}}} is a superkey. |
| | 160 | |
| | 161 | In '''Bookings''', {{{booking_id}}} is a superkey. |
| | 162 | |
| | 163 | In the junction tables (e.g., '''BookingPets'''), the composite key is the only determinant, meaning it is trivially a superkey. |
| | 164 | |
| | 165 | '''Result:''' In every single relation, the determinant is a candidate/superkey. |
| | 166 | |
| | 167 | '''Status:''' All relations naturally satisfy '''BCNF'''. The decomposition process is mathematically complete. |
| | 168 | |
| | 169 | == Final result and discussion == |
| | 170 | |
| | 171 | === Final normalized relational design === |
| | 172 | The final database schema operates in strict BCNF with the following 14 relations: |
| | 173 | |
| | 174 | '''Users''' ({{{user_id}}}, {{{username}}}, {{{first_name}}}, {{{last_name}}}, {{{password}}}, {{{email}}}) |
| | 175 | |
| | 176 | '''Admins''' ({{{admin_id}}}, {{{user_id}}}) |
| | 177 | |
| | 178 | '''PetOwners''' ({{{owner_id}}}, {{{user_id}}}) |
| | 179 | |
| | 180 | '''PetSitters''' ({{{sitter_id}}}, {{{user_id}}}) |
| | 181 | |
| | 182 | '''PetTypes''' ({{{pettype_id}}}, {{{species}}}, {{{average_lifespan}}}, {{{needs_outdoor_walk}}}) |
| | 183 | |
| | 184 | '''Pets''' ({{{pet_id}}}, {{{name}}}, {{{photo}}}, {{{age}}}, {{{special_needs}}}, {{{description}}}, {{{owner_id}}}, {{{pettype_id}}}) |
| | 185 | |
| | 186 | '''Services''' ({{{service_id}}}, {{{type}}}, {{{description}}}) |
| | 187 | |
| | 188 | '''Bookings''' ({{{booking_id}}}, {{{status}}}, {{{date_from}}}, {{{date_to}}}, {{{address}}}, {{{owner_id}}}, {{{sitter_id}}}) |
| | 189 | |
| | 190 | '''Reviews''' ({{{review_id}}}, {{{rating}}}, {{{comment}}}, {{{booking_id}}}) |
| | 191 | |
| | 192 | '''Payments''' ({{{payment_id}}}, {{{amount}}}, {{{payment_type}}}, {{{booking_id}}}) |
| | 193 | |
| | 194 | '''AdminManagement''' ({{{admin_id}}}, {{{user_id}}}) |
| | 195 | |
| | 196 | '''BookingPets''' ({{{booking_id}}}, {{{pet_id}}}) |
| | 197 | |
| | 198 | '''SitterServices''' ({{{sitter_id}}}, {{{service_id}}}) |
| | 199 | |
| | 200 | '''BookingServices''' ({{{booking_id}}}, {{{service_id}}}) |
| | 201 | |
| | 202 | === Discussion - compare with Phase 2 === |
| | 203 | 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. |