Changes between Version 3 and Version 4 of Normalization


Ignore:
Timestamp:
03/05/26 16:13:18 (2 weeks ago)
Author:
231035
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v3 v4  
    33=== Global set of attributes (single de-normalized relation)
    44This represents the initial de-normalized relation before any normalization is applied.
    5 To avoid duplicate attribute names, role-based user references are renamed.
     5Attribute names are made unique to avoid duplication.
    66{{{
    77R = {
    8 -- User / roles
    98user_id, username, email, name, surname, full_name, password_hash, user_created_at,
    109client_id, is_blocked, blocked_at, blocked_reason,
     
    1211owner_id,
    1312
    14 -- Notification
    1513notification_id, notification_type, notification_message, notification_created_at, is_read,
    1614
    17 -- Animal
    1815animal_id, animal_name, located_name, species, animal_type, breed, sex, date_of_birth, photo_url,
    1916
    20 -- Listing
    2117listing_id, listing_status, listing_created_at, price, listing_description,
    2218
    23 -- Favorite listing
    24 (saved relationship has no separate id in the ER, so it is represented by keys) saved_user_id, saved_listing_id,
    25 
    26 -- Vet clinic
     19saved_user_id, saved_listing_id,
     20
    2721clinic_id, clinic_name, clinic_email, clinic_phone, clinic_address, clinic_location, clinic_city,
    2822
    29 -- Vet clinic application
    3023application_id, app_name, app_email, app_phone, app_city, app_address, submitted_at, app_status, reviewed_at, reviewed_by, denial_reason,
    3124
    32 -- Appointment
    3325appointment_id, date_time, appointment_status, notes,
    3426
    35 -- Health record
    3627healthrecord_id, hr_type, hr_description, hr_date,
    3728
    38 -- Review (and subtypes)
    3929review_id, reviewer_id, rating, comment, review_created_at, updated_at, is_deleted,
    4030target_user_id, target_clinic_id
     
    8272Favorite Listing
    8373{{{
    84 FD15: (saved_user_id, saved_listing_id) → /
     74FD15: (saved_user_id, saved_listing_id) →
    8575}}}
    8676== Candidate keys and primary key selection
    8777=== Attributes appearing only on the left side
    8878{{{
    89 notification_id, application_id, clinic_id, animal_id, listing_id,
    90 appointment_id, healthrecord_id, review_id,
    91 timestamp-like attributes are not keys here; saved is composite.
     79user_id, client_id, admin_id, owner_id,
     80notification_id, clinic_id, application_id,
     81animal_id, listing_id, appointment_id, healthrecord_id, review_id,
     82(saved_user_id, saved_listing_id)
    9283}}}
    9384[[BR]]
     
    10091}}}
    10192Its closure includes all descriptive attributes via FD1–FD15, so it determines all attributes of R.
     93=== Closure proof for K
     94{{{
     95Let K = {notification_id, application_id, clinic_id, animal_id, listing_id,
     96         appointment_id, healthrecord_id, review_id, saved_user_id, saved_listing_id}
     97
     98Compute K+:
     99Start: K+ = K
     100
     101From FD5:
     102notification_id → notification_type, notification_message, notification_created_at, is_read, user_id
     103Add: notification_type, notification_message, notification_created_at, is_read, user_id
     104
     105From FD1:
     106user_id → username, email, name, surname, full_name, password_hash, user_created_at
     107Add: username, email, name, surname, full_name, password_hash, user_created_at
     108
     109From FD9:
     110listing_id → listing_status, listing_created_at, price, listing_description, animal_id, admin_id
     111Add: listing_status, listing_created_at, price, listing_description, admin_id
     112(animal_id already in K)
     113
     114From FD3:
     115admin_id → user_id (already in K+)
     116
     117From FD8:
     118animal_id → animal_name, located_name, species, animal_type, breed, sex, date_of_birth, photo_url, owner_id
     119Add: animal_name, located_name, species, animal_type, breed, sex, date_of_birth, photo_url, owner_id
     120
     121From FD4:
     122owner_id → client_id
     123Add: client_id
     124
     125From FD2:
     126client_id → user_id, is_blocked, blocked_at, blocked_reason
     127Add: is_blocked, blocked_at, blocked_reason (user_id already in K+)
     128
     129From FD6:
     130clinic_id → clinic_name, clinic_email, clinic_phone, clinic_address, clinic_location, clinic_city
     131Add: clinic_name, clinic_email, clinic_phone, clinic_address, clinic_location, clinic_city
     132
     133From FD7:
     134application_id → app_name, app_email, app_phone, app_city, app_address, submitted_at, app_status,
     135                 reviewed_at, reviewed_by, denial_reason, clinic_id
     136Add: app_name, app_email, app_phone, app_city, app_address, submitted_at, app_status,
     137     reviewed_at, reviewed_by, denial_reason (clinic_id already in K+)
     138
     139From FD10:
     140appointment_id → date_time, appointment_status, notes, animal_id, clinic_id
     141Add: date_time, appointment_status, notes (animal_id, clinic_id already in K+)
     142
     143From FD11:
     144healthrecord_id → hr_type, hr_description, hr_date, animal_id, appointment_id
     145Add: hr_type, hr_description, hr_date
     146
     147From FD12:
     148review_id → reviewer_id, rating, comment, review_created_at, updated_at, is_deleted
     149Add: reviewer_id, rating, comment, review_created_at, updated_at, is_deleted
     150
     151From FD13 and FD14:
     152review_id → target_user_id, target_clinic_id
     153Add: target_user_id, target_clinic_id
     154
     155FD15 adds no attributes.
     156
     157Therefore K+ = R, so K is a superkey.
     158[[BR]]
     159K is also a minimal and a candidate key.
     160}}}
    102161=== Chosen primary key
    103162We select the minimal superkey built from "left-only identifiers":
     
    151210* Reviews(review_id, reviewer_id, rating, comment, review_created_at, updated_at, is_deleted)
    152211* FavoriteListings(saved_user_id, saved_listing_id)
    153 {{{Lossless join:}}} each relation shares its determinant key(s) with the original R.
     212{{{Lossless join:}}}
     213[[BR]]
     214For each decomposition R → R1, R2, the intersection (R1 ∩ R2) is a key of at least one of the relations(user_id is key of Users etc.).So each decomposition step is lossless.
    154215{{{Dependency preservation:}}} FD1–FD15 are preserved because each FD now lives entirely inside one of the new relations.
    155216== Check for 3NF(and decomposition)
     
    193254{{{So the schema satisfies BCNF.}}}
    194255== Check for 4NF(multivalued dependencies)
    195 Potential 4NF risks usually come from independent multi-valued facts forced into one table. Here, we already separated M:N facts into their own relations:
    196 * FavoriteListings(saved_user_id, saved_listing_id) is its own table
    197 * Review subtypes are separate
    198 * Appointments and HealthRecords are separate entities (no independent repeating groups inside them)
    199 {{{So the schema satisfies 4NF.}}}
     256No additional multivalued dependencies are identified beyond the M:N relationship FavoriteListing,which is already represented as its own relation FavoriteListings(saved_user_id, saved_listing_id). So no further 4NF decomposition is required.
     257{{{The schema satisfies 4NF.}}}
    200258== Final relations
    201259* Users(user_id, username, email, name, surname, full_name, password_hash, user_created_at)
     
    227285A ClinicReview is allowed only if the reviewer has at least one Appointment at that clinic with status = 'DONE'.
    228286== Conclusion
    229 By decomposing the initial unified Petify relation using the functional dependencies derived from the ER model, we obtained a set of relations that are dependency-preserving, lossless-join, and satisfy BCNF (and effectively 4NF). This aligns with the fact that the ER model is already structured around proper entities and relationship tables (especially for saved/favorites and review subtypes).
     287The final normalized relational design matches the Phase 2 ER-based design:
     288* Each entity becomes a relation.
     289* Specializations are represented as subtype relations.
     290* The M:N relationship FavoriteListing is represented as a junction relation FavoriteListings.
     291Therefore, there are no structural differences from Phase 2.