Changes between Version 22 and Version 23 of Normalization


Ignore:
Timestamp:
04/27/26 02:46:10 (5 days ago)
Author:
221296
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v22 v23  
    281281  Because subscription details are stored in UserSubscription, they should not be repeated in Payment. Payment keeps only payment_id, user_id, subscription_id and amount, so no transitive dependency remains inside Payment.
    282282 
    283 * In Listings(listing_id, admin_id, animal_id, …), we have listing_id → admin_id and globally admin_id → user_id, but user attributes are stored in Users, not in Listings, so no transitive dependency remains inside Listings.
    284 * In VetClinicApplications(application_id, clinic_id, …), we have application_id → clinic_id and clinic_id determines clinic attributes, but those attributes are stored in VetClinics, not in VetClinicApplications, so no transitive dependency remains there either.
    285 
    286 === Review subtypes (User Review and Clinic Review)
    287 The ER model contains a specialization of Review into UserReview and ClinicReview.
    288 If both target_user_id and target_clinic_id are stored in Reviews, the relation mixes subtype-specific semantics and may introduce nulls or invalid combinations.
    289 So we decompose:
    290 {{{
    291 UserReviews(review_id, target_user_id)
    292 ClinicReviews(review_id, target_clinic_id)
    293 }}}
    294 
    295 Now:
    296 * Reviews stores the common review attributes
    297 * UserReviews stores the target user of a user review
    298 * ClinicReviews stores the target clinic of a clinic review
     283* In UserSubscription(subscription_id, user_id, plan_id, start_date, end_date, subscription_status), we have:
     284  subscription_id → plan_id
     285  plan_id → plan_name, price, duration_months, plan_description, access_type
     286  Since plan descriptive attributes are stored in SubscriptionPlan, no transitive dependency remains inside UserSubscription.
     287
     288* In Course(course_id, course_name, course_price, course_status, instructor_id), we have:
     289  course_id → instructor_id
     290  instructor_id → user_id
     291The user descriptive attributes are stored in UserEntity, not in Course, so no transitive dependency remains inside Course.
     292
     293* In QuizAttempt(attempt_id, user_id, quiz_id, score, attempt_date), we have:
     294  attempt_id → quiz_id
     295  quiz_id → lesson_id, total_points, passing_score
     296  Quiz details are stored in Quiz, so QuizAttempt does not contain transitive dependencies.
     297
     298* In Certificate(certificate_id, enrollment_id, issue_date, certificate_code, certificate_status), we have:
     299  certificate_id → enrollment_id
     300  enrollment_id → user_id, course_id, enroll_date, completion_status, progress_percentage
     301
     302  Enrollment details are stored in Enrollment, so no transitive dependency remains inside Certificate.
     303
     304*
     305=== User specializations (User, Administrator and Instructor)
     306The ER model contains a specialization of UserEntity into User, Administrator and Instructor.
     307
     308The common user attributes are stored in UserEntity:
     309
     310UserEntity(user_id, first_name, last_name, email, password, role)
     311
     312The subtype relations store only the identifier that connects the subtype with the general user entity:
     313{{{
     314Users(user_id)
     315Administrators(admin_id, user_id)
     316Instructors(instructor_id, user_id)
     317}}}
     318This avoids storing user descriptive attributes multiple times in the subtype relations. Therefore, no transitive dependency remains inside the specialization relations.
    299319
    300320=== Results after 3NF step
    301 * UserReviews(review_id, target_user_id)
    302 * ClinicReviews(review_id, target_clinic_id)
    303 
    304 After separating subtype-specific attributes into UserReviews and ClinicReviews, all resulting relations satisfy 3NF.
     321After checking the relations obtained from the 2NF decomposition, no additional decomposition is required for 3NF.
     322
     323The resulting relations after the 3NF step are:
     324
     325UserEntity(user_id, first_name, last_name, email, password, role)
     326Users(user_id)
     327Administrators(admin_id, user_id)
     328Instructors(instructor_id, user_id)
     329
     330SubscriptionPlan(plan_id, plan_name, price, duration_months, plan_description, access_type)
     331UserSubscription(subscription_id, user_id, plan_id, start_date, end_date, subscription_status)
     332Payment(payment_id, user_id, subscription_id, amount)
     333
     334SupportTicket(ticket_id, user_id, admin_id, subject, ticket_description, ticket_status, created_at)
     335
     336Category(category_id, category_name, category_description)
     337Course(course_id, course_name, course_price, course_status, instructor_id)
     338CourseCategory(course_id, category_id)
     339
     340Module(module_id, course_id, module_title, module_description)
     341Lesson(lesson_id, module_id, lesson_title, material)
     342Quiz(quiz_id, lesson_id, total_points, passing_score)
     343QuizAttempt(attempt_id, user_id, quiz_id, score, attempt_date)
     344
     345Enrollment(enrollment_id, user_id, course_id, enroll_date, completion_status, progress_percentage)
     346Certificate(certificate_id, enrollment_id, issue_date, certificate_code, certificate_status)
     347
     348All resulting relations satisfy 3NF because for every non-trivial functional dependency X → Y inside a relation, X is a key of that relation, or the dependent attributes are stored in a separate relation determined by their own key.
    305349
    306350== Check for BCNF