| 1 | | = Database Normalization – Wedding Planner System = |
| 2 | | |
| 3 | | == Introduction == |
| 4 | | |
| 5 | | This section presents a complete, formal, and provable normalization process for the Wedding Planner database. |
| 6 | | The normalization is demonstrated step by step, starting from a denormalized relation and ending in Third Normal Form (3NF). |
| 7 | | |
| 8 | | **Each transformation is justified using:** |
| 9 | | |
| 10 | | -Functional dependencies |
| 11 | | |
| 12 | | -Primary key verification |
| 13 | | |
| 14 | | -Lossless join decomposition proof |
| 15 | | |
| 16 | | -Functional dependency preservation proof |
| 17 | | |
| 18 | | All examples are derived directly from the Wedding Planner domain. |
| 19 | | |
| 20 | | == Initial Denormalized Relation (UNF) == |
| 21 | | |
| 22 | | The system initially stores all wedding-related information in a single relation. |
| 23 | | |
| 24 | | || Relation || Attributes || |
| 25 | | || R || user_id, user_first_name, user_last_name, user_email, wedding_id, wedding_date, wedding_budget, venue_id, venue_name, venue_type, venue_capacity, booking_date, start_time, end_time || |
| 26 | | |
| 27 | | This relation violates normalization principles. |
| 28 | | |
| 29 | | Note: venue_type in the UNF is an attribute that is later normalized into a separate relation. |
| 30 | | |
| 31 | | === Denormalized Table === |
| 32 | | |
| 33 | | || user_id || first_name || last_name || email || wedding_id || wedding_date || wedding_budget || event_id || event_type || event_date || start_time || end_time ||guest_id || guest_first_name || guest_last_name || rsvp_status || attendance_status || venue_name || venue_type || photographer_name || band_name || |
| 34 | | || 1 || Ana || Trajkovska || ana.trajkovska@gmail.com || 1 || 2026-06-20 || 8500 || 1 || Church Ceremony || 2026-06-20 || 12:00 || 13:00 || 1 || Ana || Markovska || accepted || attending || Lakeside Garden Venue || Outdoor Garden || Luna Studio || The Wedding Vibes || |
| 35 | | || 1 || Ana || Trajkovska || ana.trajkovska@gmail.com || 1 || 2026-06-20 || 8500 || 2 || Reception || 2026-06-20 || 16:00 || 23:00 || 2 || Daniel || Stojanov || accepted || attending || Lakeside Garden Venue || Outdoor Garden || Luna Studio || The Wedding Vibes || |
| 36 | | |
| 37 | | |
| 38 | | == Identified Problems in UNF == |
| 39 | | |
| 40 | | || Problem || Explanation || |
| 41 | | || Repetition || Venue data is repeated for every wedding |
| 42 | | || Update anomaly || Updating venue name requires multiple updates |
| 43 | | || Insertion anomaly || Venue cannot exist without a wedding |
| 44 | | || Deletion anomaly || Deleting a wedding removes venue data |
| 45 | | || Mixed entities || User, wedding, venue, and booking data stored together || |
| 46 | | |
| 47 | | == Functional Dependency Analysis == |
| 48 | | |
| 49 | | Based on business rules of the Wedding Planner system, the following functional dependencies hold: |
| 50 | | |
| 51 | | || ID || Functional Dependency || Justification || |
| 52 | | || FD1 || user_id → user_first_name, user_last_name, user_email || User attributes depend only on user_id |
| 53 | | || FD2 || wedding_id → wedding_date, wedding_budget, user_id || A wedding uniquely defines its properties |
| 54 | | || FD3 || venue_id → venue_name, venue_type, venue_capacity || Venue attributes depend only on venue_id |
| 55 | | || FD4 || booking_id → venue_id, wedding_id, booking_date, start_time, end_time || A booking uniquely defines a venue reservation || |
| | 1 | = Wedding Planner Database Normalization = |
| | 2 | |
| | 3 | == Denormalized Form == |
| | 4 | |
| | 5 | A single flat relation initially stores all entities and relationships of the Wedding Planner system in one table, without structural separation. |
| | 6 | This causes repeating groups, redundancy, update anomalies, insertion anomalies, and deletion anomalies. |
| | 7 | |
| | 8 | === Initial Denormalized Relation === |
| | 9 | |
| | 10 | R( |
| | 11 | user_id, first_name, last_name, email, phone_number, gender, birthday, |
| | 12 | wedding_id, date, budget, notes, |
| | 13 | venue_booking_id, vb_date, vb_start, vb_end, vb_status, vb_price, |
| | 14 | venue_id, venue_name, location, city, capacity, price_per_guest, venue_type, |
| | 15 | photographer_id, photographer_name, photo_price_per_hour, |
| | 16 | band_id, band_name, band_genre, band_price_per_hour, |
| | 17 | registrar_id, registrar_name, registrar_location, |
| | 18 | church_id, church_name, priest_name, |
| | 19 | guest_id, guest_first_name, guest_last_name, rsvp_status, attendance_status, table_number, event_type |
| | 20 | ) |
| | 21 | |
| | 22 | == Functional Dependencies == |
| | 23 | |
| | 24 | The following functional dependencies hold in the Wedding Planner system: |
| | 25 | |
| | 26 | user_id → first_name, last_name, email, phone_number, gender, birthday |
| | 27 | wedding_id → date, budget, notes, user_id |
| | 28 | event_id → event_type, date, start_time, end_time, status, wedding_id |
| | 29 | guest_id → guest_first_name, guest_last_name, email, wedding_id |
| | 30 | response_id → status, response_date, guest_id, event_id |
| | 31 | attendance_id → status, table_number, role, guest_id, event_id |
| | 32 | venue_booking_id → vb_date, vb_start, vb_end, vb_status, vb_price, venue_id, wedding_id |
| | 33 | venue_id → venue_name, location, city, address, capacity, menu, phone_number, price_per_guest, type_id |
| | 34 | type_id → type_name |
| | 35 | photographer_booking_id → date, start_time, end_time, status, photographer_id, wedding_id |
| | 36 | photographer_id → photographer_name, email, phone_number, price_per_hour |
| | 37 | band_booking_id → date, start_time, end_time, status, band_id, wedding_id |
| | 38 | band_id → band_name, band_genre, equipment, phone_number, price_per_hour |
| | 39 | registrar_booking_id → start_time, end_time, price, status, registrar_id, wedding_id |
| | 40 | registrar_id → registrar_name, contact, location, working_hours |
| | 41 | church_id → church_name, location, contact, wedding_id |
| | 42 | priest_id → priest_name, contact, church_id |
| | 43 | |
| | 44 | === Additional Business Constraints === |
| | 45 | |
| | 46 | The following additional dependencies also hold: |
| | 47 | |
| | 48 | {guest_id, event_id} → {response_id, rsvp_status, response_date} |
| | 49 | {guest_id, event_id} → {attendance_id, attendance_status, table_number} |
| | 50 | {venue_id, vb_date, vb_start} → {venue_booking_id} |
| | 51 | {wedding_id} → {venue_booking_id, photographer_booking_id, band_booking_id, registrar_booking_id, church_id} |
| 100 | | *It is in 1NF |
| 101 | | |
| 102 | | *No non-key attribute is partially dependent on a composite key |
| 103 | | |
| 104 | | === Partial Dependency Proof === |
| 105 | | |
| 106 | | || Attribute || Depends On || Violation || |
| 107 | | || user_first_name || user_id || Partial dependency |
| 108 | | || wedding_date || wedding_id || Partial dependency |
| 109 | | || venue_name || venue_id || Partial dependency |
| 110 | | |
| 111 | | Thus, 2NF is violated in the original relation. |
| 112 | | |
| 113 | | === Decomposition to 2NF === |
| 114 | | |
| 115 | | || Table || Primary Key || Attributes || |
| 116 | | || user || user_id || user_first_name, user_last_name, user_email |
| 117 | | || wedding || wedding_id || wedding_date, wedding_budget, user_id |
| 118 | | || venue || venue_id || venue_name, venue_type, venue_capacity |
| 119 | | || venue_booking || booking_id || venue_id, wedding_id, booking_date, start_time, end_time |
| 120 | | |
| 121 | | Each non-key attribute now fully depends on the primary key. |
| 122 | | |
| 123 | | == Explanation of Entity Composition (User Table) == |
| 124 | | |
| 125 | | The user table exists because user data represents an independent entity. |
| 126 | | |
| 127 | | || Reason || Formal Explanation || |
| 128 | | || Functional dependency || user_id → user attributes |
| 129 | | || Independence || User may exist without a wedding |
| 130 | | || Reusability || One user can manage multiple weddings |
| 131 | | || Normalization rule || Prevents transitive dependencies || |
| 132 | | |
| 133 | | This decomposition is mandatory for correctness. |
| 134 | | |
| 135 | | Please review the proof explained in more details here -> [[Proof of 2N]] |
| | 137 | It is already in 1NF |
| | 138 | Every non-key attribute is fully functionally dependent on the entire primary key |
| | 139 | No partial dependencies exist |
| | 140 | |
| | 141 | === Partial Dependency Violations === |
| | 142 | |
| | 143 | The original relation violates 2NF because: |
| | 144 | |
| | 145 | user_id → user attributes |
| | 146 | wedding_id → wedding attributes |
| | 147 | venue_id → venue attributes |
| | 148 | |
| | 149 | These dependencies rely only on part of the composite key. |
| | 150 | |
| | 151 | === Decomposition into 2NF Relations === |
| | 152 | |
| | 153 | || Relation || Primary Key || |
| | 154 | || USER || user_id || |
| | 155 | || WEDDING || wedding_id || |
| | 156 | || VENUE_TYPE || type_id || |
| | 157 | || VENUE || venue_id || |
| | 158 | || VENUE_BOOKING || booking_id || |
| | 159 | || PHOTOGRAPHER || photographer_id || |
| | 160 | || PHOTOGRAPHER_BOOKING || booking_id || |
| | 161 | || BAND || band_id || |
| | 162 | || BAND_BOOKING || booking_id || |
| | 163 | || REGISTRAR || registrar_id || |
| | 164 | || REGISTRAR_BOOKING || booking_id || |
| | 165 | || CHURCH || church_id || |
| | 166 | || PRIEST || priest_id || |
| | 167 | || EVENT || event_id || |
| | 168 | || GUEST || guest_id || |
| | 169 | || EVENT_RSVP || response_id || |
| | 170 | || ATTENDANCE || attendance_id || |
| | 171 | |
| | 172 | Each resulting relation contains attributes fully dependent on its primary key. |
| | 173 | |
| | 174 | === Lossless Join Verification === |
| | 175 | |
| | 176 | Every decomposition satisfies the lossless join condition: |
| | 177 | |
| | 178 | (Ri ∩ Rj) → Ri OR (Ri ∩ Rj) → Rj |
| | 179 | |
| | 180 | Examples: |
| | 181 | |
| | 182 | || Join || Common Attribute || Proof || |
| | 183 | || USER ⋈ WEDDING || user_id || user_id is PK in USER || |
| | 184 | || VENUE_BOOKING ⋈ VENUE || venue_id || venue_id is PK in VENUE || |
| | 185 | || EVENT_RSVP ⋈ EVENT || event_id || event_id is PK in EVENT || |
| | 186 | |
| | 187 | Therefore all decompositions are lossless. |
| 145 | | |
| 146 | | === Transitive Dependency Analysis === |
| 147 | | |
| 148 | | || Dependency Chain || Explanation || |
| 149 | | || wedding_id → user_id → user_email || Transitive dependency |
| 150 | | || booking_id → venue_id → venue_name || Transitive dependency |
| 151 | | |
| 152 | | === Removal of Transitive Dependencies === |
| 153 | | |
| 154 | | Each dependency is isolated into its own table, resulting in full 3NF compliance. |
| 155 | | |
| 156 | | == Primary Key Verification == |
| 157 | | |
| 158 | | Each table has a primary key that uniquely identifies records. |
| 159 | | |
| 160 | | || Table || Primary Key || Uniqueness Proof || |
| 161 | | || user || user_id || One user per ID |
| 162 | | || wedding || wedding_id || One wedding per ID |
| 163 | | || venue || venue_id || One venue per ID |
| 164 | | || venue_booking || booking_id || One booking per ID || |
| 165 | | |
| 166 | | This ensures entity integrity and in all resulting relations, no non-key attribute functionally determines another non-key attribute. |
| 167 | | |
| 168 | | Please review the proof explained in more details here -> [[Proof of 3N]] |
| 169 | | |
| 170 | | == Lossless Join Decomposition Proof == |
| 171 | | |
| 172 | | === Formal Rule === |
| 173 | | |
| 174 | | A decomposition of R into R1 and R2 is lossless if: |
| 175 | | |
| 176 | | || Condition || |
| 177 | | || (R1 ∩ R2) → R1 OR (R1 ∩ R2) → R2 || |
| 178 | | |
| 179 | | === Step-by-Step Explanation === |
| 180 | | |
| 181 | | || Join || Common Attribute || Proof || |
| 182 | | || wedding ⋈ user || user_id || user_id is PK in user |
| 183 | | || venue_booking ⋈ wedding || wedding_id || wedding_id is PK |
| 184 | | || venue_booking ⋈ venue || venue_id || venue_id is PK |
| 185 | | |
| 186 | | Each decomposition satisfies the lossless join condition. |
| 187 | | |
| 188 | | ❗ Lossless join is proven pairwise, not by joining all tables simultaneously. |
| 189 | | |
| 190 | | == Functional Dependency Preservation Proof == |
| 191 | | |
| 192 | | === Definition === |
| 193 | | A decomposition preserves dependencies if all FDs can be enforced without joins. |
| 194 | | |
| 195 | | === Verification === |
| 196 | | |
| 197 | | || Functional Dependency || Table || |
| 198 | | || user_id → user_first_name, user_last_name, user_email || user |
| 199 | | || wedding_id → wedding_date, wedding_budget, user_id || wedding |
| 200 | | || venue_id → venue_name, venue_type, venue_capacity || venue |
| 201 | | || booking_id → venue_id, wedding_id, booking_date, start_time, end_time || venue_booking || |
| 202 | | |
| 203 | | All dependencies are preserved locally. |
| 204 | | |
| 205 | | == Final Normalized Schema (3NF) == |
| 206 | | |
| 207 | | || Table || Primary Key || Foreign Keys || |
| 208 | | || user || user_id |
| 209 | | || wedding || wedding_id || user_id → user |
| 210 | | || venue || venue_id |
| 211 | | || venue_booking || booking_id || venue_id → venue, wedding_id → wedding || |
| | 197 | Every non-key attribute depends only on the primary key |
| | 198 | |
| | 199 | === Transitive Dependency Example === |
| | 200 | |
| | 201 | venue_id → type_id → type_name |
| | 202 | |
| | 203 | Here, type_name depends transitively on venue_id through type_id. |
| | 204 | |
| | 205 | === Resolution === |
| | 206 | |
| | 207 | To eliminate the transitive dependency: |
| | 208 | |
| | 209 | VENUE_TYPE(type_id, type_name) is created |
| | 210 | VENUE stores type_id as a foreign key |
| | 211 | |
| | 212 | This removes the transitive dependency while preserving all functional dependencies. |
| | 213 | |
| | 214 | === Final 3NF Relations === |
| | 215 | |
| | 216 | || Relation || Primary Key || Foreign Keys || |
| | 217 | || USER || user_id || — || |
| | 218 | || WEDDING || wedding_id || user_id → USER || |
| | 219 | || VENUE_TYPE || type_id || — || |
| | 220 | || VENUE || venue_id || type_id → VENUE_TYPE || |
| | 221 | || VENUE_BOOKING || booking_id || venue_id → VENUE, wedding_id → WEDDING || |
| | 222 | || PHOTOGRAPHER || photographer_id || — || |
| | 223 | || PHOTOGRAPHER_BOOKING || booking_id || photographer_id → PHOTOGRAPHER, wedding_id → WEDDING || |
| | 224 | || BAND || band_id || — || |
| | 225 | || BAND_BOOKING || booking_id || band_id → BAND, wedding_id → WEDDING || |
| | 226 | || REGISTRAR || registrar_id || — || |
| | 227 | || REGISTRAR_BOOKING || booking_id || registrar_id → REGISTRAR, wedding_id → WEDDING || |
| | 228 | || CHURCH || church_id || wedding_id → WEDDING || |
| | 229 | || PRIEST || priest_id || church_id → CHURCH || |
| | 230 | || EVENT || event_id || wedding_id → WEDDING || |
| | 231 | || GUEST || guest_id || wedding_id → WEDDING || |
| | 232 | || EVENT_RSVP || response_id || guest_id → GUEST, event_id → EVENT || |
| | 233 | || ATTENDANCE || attendance_id || guest_id → GUEST, event_id → EVENT || |
| | 234 | |
| | 235 | == BCNF Verification == |
| | 236 | |
| | 237 | A relation is in BCNF if for every non-trivial dependency: |
| | 238 | |
| | 239 | X → Y |
| | 240 | |
| | 241 | X is a superkey. |
| | 242 | |
| | 243 | All final relations satisfy this condition because every determinant is a candidate key or superkey. |
| 215 | | The Wedding Planner database schema is fully normalized to Third Normal Form. |
| 216 | | |
| 217 | | The normalization: |
| 218 | | |
| 219 | | -Eliminates redundancy |
| 220 | | |
| 221 | | -Prevents anomalies |
| 222 | | |
| 223 | | -Preserves functional dependencies |
| 224 | | |
| 225 | | -Guarantees lossless joins |
| 226 | | |
| 227 | | -Uses provable primary keys |
| | 247 | The Wedding Planner database schema has been formally normalized to Third Normal Form (3NF) and BCNF. |
| | 248 | |
| | 249 | The normalization process: |
| | 250 | |
| | 251 | Eliminates redundancy |
| | 252 | Prevents update anomalies |
| | 253 | Prevents insertion anomalies |
| | 254 | Prevents deletion anomalies |
| | 255 | Preserves functional dependencies |
| | 256 | Guarantees lossless joins |
| | 257 | Ensures entity integrity through verified primary keys |
| | 258 | |
| | 259 | The final schema consists of 17 fully normalized relations. |
| | 260 | |
| | 261 | = Proof of Candidate Key = |
| | 262 | |
| | 263 | == Definition == |
| | 264 | |
| | 265 | A set of attributes X is a candidate key if: |
| | 266 | |
| | 267 | X⁺ = R |
| | 268 | X is minimal |
| | 269 | |
| | 270 | The closure X⁺ is computed by repeatedly applying functional dependencies until no additional attributes can be derived. |
| | 271 | |
| | 272 | == Step 1 – Testing Single Attribute Candidate Keys == |
| | 273 | |
| | 274 | === Attempt 1 === |
| | 275 | |
| | 276 | K = {attendance_id} |
| | 277 | |
| | 278 | === Closure === |
| | 279 | |
| | 280 | (attendance_id)⁺ gives: |
| | 281 | |
| | 282 | attendance_status |
| | 283 | table_number |
| | 284 | guest_id |
| | 285 | event_id |
| | 286 | |
| | 287 | Using additional dependencies: |
| | 288 | |
| | 289 | event_id → event_type, wedding_id |
| | 290 | guest_id → guest_first_name, guest_last_name, rsvp_status, wedding_id |
| | 291 | wedding_id → date, budget, notes, user_id |
| | 292 | user_id → first_name, last_name, email, phone_number, gender, birthday |
| | 293 | |
| | 294 | === Missing Dependencies === |
| | 295 | |
| | 296 | The closure still does NOT determine: |
| | 297 | |
| | 298 | venue booking information |
| | 299 | photographer booking information |
| | 300 | band booking information |
| | 301 | registrar booking information |
| | 302 | priest and church information |
| | 303 | |
| | 304 | Therefore: |
| | 305 | |
| | 306 | (attendance_id)⁺ ≠ R |
| | 307 | |
| | 308 | Conclusion: |
| | 309 | |
| | 310 | attendance_id is NOT a candidate key. |
| | 311 | |
| | 312 | == Step 2 – Testing Two Attributes == |
| | 313 | |
| | 314 | K = {attendance_id, priest_id} |
| | 315 | |
| | 316 | === Closure === |
| | 317 | |
| | 318 | Additional attributes derived: |
| | 319 | |
| | 320 | priest_name |
| | 321 | priest_contact |
| | 322 | church_id |
| | 323 | church_name |
| | 324 | church_location |
| | 325 | |
| | 326 | === Missing Dependencies === |
| | 327 | |
| | 328 | Still missing: |
| | 329 | |
| | 330 | venue booking information |
| | 331 | photographer booking information |
| | 332 | band booking information |
| | 333 | registrar booking information |
| | 334 | |
| | 335 | Therefore: |
| | 336 | |
| | 337 | (attendance_id, priest_id)⁺ ≠ R |
| | 338 | |
| | 339 | Conclusion: |
| | 340 | |
| | 341 | K is NOT a candidate key. |
| | 342 | |
| | 343 | == Step 3 – Testing Three Attributes == |
| | 344 | |
| | 345 | K = { |
| | 346 | attendance_id, |
| | 347 | venue_booking_id, |
| | 348 | photographer_booking_id |
| | 349 | } |
| | 350 | |
| | 351 | === Closure === |
| | 352 | |
| | 353 | Additional attributes derived: |
| | 354 | |
| | 355 | venue information |
| | 356 | photographer information |
| | 357 | wedding information |
| | 358 | user information |
| | 359 | |
| | 360 | === Missing Dependencies === |
| | 361 | |
| | 362 | Still missing: |
| | 363 | |
| | 364 | band booking information |
| | 365 | registrar booking information |
| | 366 | priest/church information |
| | 367 | |
| | 368 | Therefore: |
| | 369 | |
| | 370 | K⁺ ≠ R |
| | 371 | |
| | 372 | Conclusion: |
| | 373 | |
| | 374 | K is NOT a candidate key. |
| | 375 | |
| | 376 | == Step 4 – Testing Larger Attribute Sets == |
| | 377 | |
| | 378 | K = { |
| | 379 | attendance_id, |
| | 380 | priest_id, |
| | 381 | venue_booking_id, |
| | 382 | band_booking_id |
| | 383 | } |
| | 384 | |
| | 385 | === Missing Dependencies === |
| | 386 | |
| | 387 | Still missing: |
| | 388 | |
| | 389 | photographer booking information |
| | 390 | registrar booking information |
| | 391 | |
| | 392 | Therefore: |
| | 393 | |
| | 394 | K⁺ ≠ R |
| | 395 | |
| | 396 | Conclusion: |
| | 397 | |
| | 398 | K is NOT a candidate key. |
| | 399 | |
| | 400 | == Step 5 – Including All Booking Branches == |
| | 401 | |
| | 402 | K = { |
| | 403 | attendance_id, |
| | 404 | venue_booking_id, |
| | 405 | photographer_booking_id, |
| | 406 | band_booking_id, |
| | 407 | registrar_booking_id |
| | 408 | } |
| | 409 | |
| | 410 | === Missing Dependencies === |
| | 411 | |
| | 412 | Still missing: |
| | 413 | |
| | 414 | priest information |
| | 415 | church information |
| | 416 | |
| | 417 | Therefore: |
| | 418 | |
| | 419 | K⁺ ≠ R |
| | 420 | |
| | 421 | Conclusion: |
| | 422 | |
| | 423 | K is NOT a candidate key. |
| | 424 | |
| | 425 | == Step 6 – Final Candidate Key == |
| | 426 | |
| | 427 | K = { |
| | 428 | attendance_id, |
| | 429 | venue_booking_id, |
| | 430 | photographer_booking_id, |
| | 431 | band_booking_id, |
| | 432 | registrar_booking_id, |
| | 433 | priest_id |
| | 434 | } |
| | 435 | |
| | 436 | === Closure === |
| | 437 | |
| | 438 | Using all functional dependencies: |
| | 439 | |
| | 440 | attendance branch is determined |
| | 441 | event branch is determined |
| | 442 | guest branch is determined |
| | 443 | wedding branch is determined |
| | 444 | venue booking branch is determined |
| | 445 | photographer booking branch is determined |
| | 446 | band booking branch is determined |
| | 447 | registrar booking branch is determined |
| | 448 | priest branch is determined |
| | 449 | church branch is determined |
| | 450 | |
| | 451 | No attributes remain undetermined. |
| | 452 | |
| | 453 | Therefore: |
| | 454 | |
| | 455 | K⁺ = R |
| | 456 | |
| | 457 | Conclusion: |
| | 458 | |
| | 459 | K is a candidate key. |
| | 460 | |
| | 461 | == Minimality Proof == |
| | 462 | |
| | 463 | A candidate key must be minimal. |
| | 464 | |
| | 465 | Removing any attribute from K causes loss of at least one independent entity branch: |
| | 466 | |
| | 467 | || Removed Attribute || Lost Information || |
| | 468 | || attendance_id || attendance branch || |
| | 469 | || venue_booking_id || venue booking branch || |
| | 470 | || photographer_booking_id || photographer booking branch || |
| | 471 | || band_booking_id || band booking branch || |
| | 472 | || registrar_booking_id || registrar booking branch || |
| | 473 | || priest_id || priest/church branch || |
| | 474 | |
| | 475 | Therefore every attribute in K is necessary. |
| | 476 | |
| | 477 | == Why church_id Is Not Included == |
| | 478 | |
| | 479 | Suppose we define: |
| | 480 | |
| | 481 | K = { |
| | 482 | attendance_id, |
| | 483 | venue_booking_id, |
| | 484 | photographer_booking_id, |
| | 485 | band_booking_id, |
| | 486 | registrar_booking_id, |
| | 487 | priest_id, |
| | 488 | church_id |
| | 489 | } |
| | 490 | |
| | 491 | This violates minimality because: |
| | 492 | |
| | 493 | priest_id → church_id |
| | 494 | |
| | 495 | church_id is already derivable from priest_id. |
| | 496 | |
| | 497 | Therefore church_id is redundant. |
| | 498 | |
| | 499 | The resulting set would be a superkey, NOT a candidate key. |
| | 500 | |
| | 501 | == Final Candidate Key == |
| | 502 | |
| | 503 | K = { |
| | 504 | attendance_id, |
| | 505 | venue_booking_id, |
| | 506 | photographer_booking_id, |
| | 507 | band_booking_id, |
| | 508 | registrar_booking_id, |
| | 509 | priest_id |
| | 510 | } |
| | 511 | |
| | 512 | This key: |
| | 513 | |
| | 514 | Determines all attributes of R |
| | 515 | Is minimal |
| | 516 | Satisfies the formal definition of a candidate key |