Changes between Version 7 and Version 8 of Normalization


Ignore:
Timestamp:
08/22/26 19:11:29 (8 hours ago)
Author:
231035
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v7 v8  
    189189}}}
    190190
    191 Therefore, K+ determines all attributes of R, so K is a superkey. It is minimal because removing any identifier loses one independent component of the universal relation: notification, application, listing, health record, review, favorite pair, or unavailable slot.
     191Therefore, K+ determines all attributes of R, so K is a superkey.
     192
     193=== Proof that there are no other candidate keys
     194
     195To promote K from only "a candidate key" to the chosen primary key, we also need to show that no other candidate key exists.
     196
     197In the given set of functional dependencies, the following identifiers represent independent components of the universal relation:
     198{{{
     199notification_id,
     200application_id,
     201listing_id,
     202healthrecord_id,
     203review_id,
     204favorite_user_id,
     205favorite_listing_id,
     206slot_id
     207}}}
     208
     209None of these attributes is functionally determined by another determinant in the given FD set:
     210* notification_id does not appear on the right-hand side of any FD, so it cannot be derived.
     211* application_id does not appear on the right-hand side of any FD, so it cannot be derived.
     212* listing_id does not appear on the right-hand side of any FD, so it cannot be derived.
     213* healthrecord_id does not appear on the right-hand side of any FD, so it cannot be derived.
     214* review_id does not appear on the right-hand side of any FD, so it cannot be derived.
     215* favorite_user_id and favorite_listing_id identify the saved_by relationship. Since FavoriteListing has no non-trivial FD that derives either component, both are required.
     216* slot_id does not appear on the right-hand side of any FD, so it cannot be derived.
     217
     218Therefore every superkey of R must contain all attributes in:
     219{{{
     220E = {notification_id, application_id, listing_id, healthrecord_id, review_id,
     221     favorite_user_id, favorite_listing_id, slot_id}
     222}}}
     223
     224Since K = E and K+ = R, K is a superkey. Since every superkey must contain E, no smaller key can exist. Also, no different candidate key can be formed by replacing one of these attributes with another attribute, because none of the required attributes in E can be derived from any other FD determinant.
     225
     226Thus K is the only candidate key of the initial de-normalized relation under the stated functional dependencies.
    192227
    193228The chosen primary key of the initial de-normalized relation is:
    194 {{{
     229{{{ 
    195230{notification_id, application_id, listing_id, healthrecord_id, review_id,
    196231 favorite_user_id, favorite_listing_id, slot_id}
     
    253288{{{Lossless join:}}}
    254289[[BR]]
    255 The decomposition is lossless because each decomposed relation is formed around a determinant that becomes the key of that relation. Foreign keys preserve the relationships between the decomposed relations.
     290We use the binary lossless decomposition criterion:
     291For a decomposition of relation R into R1 and R2, the decomposition is lossless if:
     292{{{
     293(R1 ∩ R2) -> R1
     294or
     295(R1 ∩ R2) -> R2
     296}}}
     297
     298The 2NF decomposition can be seen as repeated binary decompositions. At each step, a relation is split off using a determinant X, and X remains in the remaining relation as the join attribute. Since X functionally determines all attributes in the new relation, the join is lossless.
     299
     300Step-by-step:
     301{{{
     3021. Split Users(user_id, username, email, name, surname, password_hash, created_at)
     303   Intersection with remaining relation: user_id
     304   FD1 gives user_id -> Users
     305   Therefore the join is lossless.
     306
     3072. Split Admins(user_id)
     308   Intersection with remaining relation: user_id
     309   user_id is the key of Admins
     310   Therefore the join is lossless.
     311
     3123. Split Clients(user_id, is_blocked, blocked_at, blocked_reason, blocked_by)
     313   Intersection with remaining relation: user_id
     314   FD3 gives client_user_id -> client attributes, and in the final schema client_user_id is represented as user_id
     315   Therefore the join is lossless.
     316
     3174. Split Owners(user_id)
     318   Intersection with remaining relation: user_id
     319   user_id is the key of Owners
     320   Therefore the join is lossless.
     321
     3225. Split VetClinics(clinic_id, user_id, name, email, phone, location, city, address, work_days, start_time, end_time)
     323   Intersection with remaining relation: clinic_id
     324   FD5 gives clinic_id -> VetClinics
     325   Therefore the join is lossless.
     326
     3276. Split Notifications(notification_id, user_id, type, message, is_read, created_at)
     328   Intersection with remaining relation: notification_id
     329   FD6 gives notification_id -> Notifications
     330   Therefore the join is lossless.
     331
     3327. Split VetClinicApplications(application_id, clinic_id, name, email, phone, city, address, submitted_at, status, reviewed_at, reviewed_by, denial_reason)
     333   Intersection with remaining relation: application_id
     334   FD7 gives application_id -> VetClinicApplications
     335   Therefore the join is lossless.
     336
     3378. Split Animals(animal_id, owner_id, name, located_name, species, type, breed, sex, date_of_birth, photo_url)
     338   Intersection with remaining relation: animal_id
     339   FD8 gives animal_id -> Animals
     340   Therefore the join is lossless.
     341
     3429. Split Listings(listing_id, owner_id, animal_id, status, created_at, price, description)
     343   Intersection with remaining relation: listing_id
     344   FD9 gives listing_id -> Listings
     345   Therefore the join is lossless.
     346
     34710. Split FavoriteListings(user_id, listing_id)
     348    Intersection with remaining relation: user_id, listing_id
     349    (user_id, listing_id) is the composite key of FavoriteListings
     350    Therefore the join is lossless.
     351
     35211. Split Appointments(appointment_id, clinic_id, animal_id, responsible_owner_id, date_time, status, notes)
     353    Intersection with remaining relation: appointment_id
     354    FD10 gives appointment_id -> Appointments
     355    Therefore the join is lossless.
     356
     35712. Split HealthRecords(healthrecord_id, animal_id, appointment_id, type, description, date)
     358    Intersection with remaining relation: healthrecord_id
     359    FD11 gives healthrecord_id -> HealthRecords
     360    Therefore the join is lossless.
     361
     36213. Split Reviews(review_id, reviewer_id, rating, comment, created_at, updated_at, is_deleted)
     363    Intersection with remaining relation: review_id
     364    FD12 gives review_id -> Reviews
     365    Therefore the join is lossless.
     366
     36714. Split UserReviews(review_id, target_user_id, interaction_type)
     368    Intersection with Reviews: review_id
     369    review_id is the key of UserReviews and also references Reviews(review_id)
     370    Therefore joining Reviews with UserReviews is lossless for user-review tuples.
     371
     37215. Split ClinicReviews(review_id, target_clinic_id, appointment_id)
     373    Intersection with Reviews: review_id
     374    review_id is the key of ClinicReviews and also references Reviews(review_id)
     375    Therefore joining Reviews with ClinicReviews is lossless for clinic-review tuples.
     376
     37716. Split ClinicUnavailableSlots(slot_id, clinic_id, date_time, reason, created_at)
     378    Intersection with remaining relation: slot_id
     379    FD15 gives slot_id -> ClinicUnavailableSlots
     380    Therefore the join is lossless.
     381}}}
     382
     383Because every decomposition step satisfies the binary lossless decomposition criterion, the whole decomposition is lossless by induction: after each split, the remaining relation can be joined back with the new relation without producing spurious tuples or losing tuples.
    256384
    257385{{{Dependency preservation:}}}