Changes between Version 21 and Version 22 of Normalization


Ignore:
Timestamp:
09/15/26 12:58:12 (12 days ago)
Author:
232012
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v21 v22  
    272272
    273273In each case, a proper subset of the candidate key determines non-prime attributes. Therefore, R contains partial functional dependencies
    274 and is not in 2NF.
    275 
    276 ==== 1. PRODUCT(product_id, format, price, product_description, stock)
    277 
    278 
    279 {{{
    280 R1 = R - {release_id, format, price, product_description, stock}
    281 
    282 R1 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_type, discount_percentage, points_collected,
    283       artist_id, artist_name, artist_description, artist_photo, release_id, title, record_label, genre, release_date, cover_photo, duration,
    284       album_id, song_id, song_name, song_duration, order_id, payment_method, purchase_date, points_earned, points_used, status, modification_id,
    285       admin_id, date_modified, type_of_modification, discount, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal,
    286       type, song_ordinal, product_id}
    287 }}}
    288 
    289 * **Lossless join:** The original relation can be reconstructed through a join using {{{product_id}}}.
    290 
    291 * **Dependency preservation:** The dependency {{{product_id → release_id, format, price, product_description, stock}}} is preserved in the new ''PRODUCT'' relation.
     274and is not in 2NF, requiring a 2NF decomposition.
     275
     276
     277The order of decomposition is not arbitrary. Relations are extracted in an order that ensures that an intermediate determinant remains available until every dependency that requires it has been handled.
     278
     279In particular:
     280
     281* {{{release_id}}} must remain available until RELEASE_ARTISTS is extracted, because {{{(release_id, artist_id) → release_ordinal, type}}}.
     282* {{{admin_id}}} must remain available until ADMIN is extracted, before it is later removed together with MODIFICATION.
     283* {{{user_id}}} must remain available until USER, CONSUMER and WISHLIST are extracted, before it is later removed as part of ORDER.
     284* {{{wishlist_id}}} must remain available until WISHLIST_PRODUCTS is extracted.
     285* {{{release_id}}} is only removed from the residual relation when PRODUCT is decomposed at the end.
     286
     287This order therefore preserves the determinants required by later decompositions and avoids removing an attribute before all dependencies involving it have been handled.
     288
     289
     290==== 1. RELEASE(release_id, title, record_label, genre, release_date, cover_photo, duration)
     291
     292The attributes of RELEASE are determined by {{{release_id}}}:
     293
     294{{{
     295release_id → title, record_label, genre, release_date, cover_photo, duration
     296}}}
     297
     298Although {{{release_id}}} is not itself part of K, it is determined by the proper subset {{{product_id}}} of K:
     299
     300{{{
     301product_id → release_id
     302}}}
     303
     304Therefore, by transitivity:
     305
     306{{{
     307product_id → title, record_label, genre, release_date, cover_photo, duration
     308}}}
     309
     310so these attributes are partially dependent on the candidate key.
     311
     312{{{
     313R1 = R - {title, record_label, genre, release_date, cover_photo, duration}
     314
     315R1 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_id, admin_type, discount_percentage,
     316      points_collected, artist_id, artist_name, artist_description, artist_photo, release_id, album_id, song_id, song_name, song_duration,
     317      product_id, format, price, product_description, stock, order_id, payment_method, purchase_date, points_earned, points_used, status,
     318      modification_id, date_modified, type_of_modification, discount, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal, type,
     319      song_ordinal}
     320}}}
     321
     322* **Lossless join:** The intersection between RELEASE and R1 is {{{release_id}}}. Since {{{release_id → title, record_label, genre, release_date, cover_photo, duration}}}, {{{release_id}}} functionally determines all attributes of RELEASE. Therefore, joining RELEASE and R1 on {{{release_id}}} reconstructs the original information.
     323
     324* **Dependency preservation:** FD07 is represented entirely inside RELEASE. Therefore {{{release_id → title, record_label, genre, release_date, cover_photo, duration}}} can still be enforced directly on this relation without joining it to another relation.
    292325
    293326
    294327==== 2. ARTIST(artist_id, artist_name, artist_description, artist_photo)
    295328
     329The determinant {{{artist_id}}} is a proper subset of K:
     330
     331{{{
     332artist_id → artist_name, artist_description, artist_photo
     333}}}
     334
     335Therefore these attributes are partially dependent on K.
    296336
    297337{{{
    298338R2 = R1 - {artist_name, artist_description, artist_photo}
    299339
    300 R2 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_type, discount_percentage, points_collected,
    301       artist_id, release_id, title, record_label, genre, release_date, cover_photo, duration, album_id, song_id, song_name, song_duration,
    302       product_id, order_id, payment_method, purchase_date, points_earned, points_used, status, modification_id, admin_id, date_modified,
    303       type_of_modification, discount, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal, type, song_ordinal}
    304 }}}
    305 
    306 * **Lossless join:** The original relation can be reconstructed through a join using {{{artist_id}}}.
    307 
    308 * **Dependency preservation:** The dependency {{{artist_id → artist_name, artist_description, artist_photo}}} is preserved in the new ''ARTIST'' relation.
    309 
    310 
    311 ==== 3. RELEASE(release_id, title, record_label, genre, release_date, cover_photo, duration)
    312 
    313 {{{
    314 R3 = R2 - {title, record_label, genre, release_date, cover_photo, duration}
    315 
    316 R3 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_type, discount_percentage, points_collected,
    317       artist_id, release_id, album_id, song_id, song_name, song_duration, product_id, order_id, payment_method, purchase_date,
    318       points_earned, points_used, status, modification_id, admin_id, date_modified, type_of_modification, discount, wishlist_id,
    319       quantity, price_at_purchase, added_at, release_ordinal, type, song_ordinal}
    320 }}}
    321 
    322 * **Lossless join:** The original relation can be reconstructed through a join using {{{release_id}}}.
    323 
    324 * **Dependency preservation:** The dependency {{{release_id → title, record_label, genre, release_date, cover_photo}}} is preserved in the new ''RELEASE'' relation.
    325 
    326 ==== 4. SONG(song_id, song_name, song_duration)
    327 
    328 {{{
    329 R4 = R3 - {song_name, song_duration}
    330 
    331 R4 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_type, discount_percentage, points_collected,
    332       artist_id, release_id, album_id, song_id, product_id, order_id, payment_method, purchase_date, points_earned, points_used, status,
    333       modification_id, admin_id, date_modified, type_of_modification, discount, wishlist_id, quantity, price_at_purchase, added_at,
     340R2 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_id, admin_type, discount_percentage,
     341      points_collected, artist_id, release_id, album_id, song_id, song_name, song_duration, product_id, format, price, product_description, stock,
     342      order_id, payment_method, purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount,
     343      wishlist_id, quantity, price_at_purchase, added_at, release_ordinal, type, song_ordinal}
     344}}}
     345
     346* **Lossless join:** ARTIST and R2 intersect on {{{artist_id}}}. Since {{{artist_id}}} is the key of ARTIST and determines all its other attributes, the original relation can be reconstructed by joining on {{{artist_id}}} without creating spurious tuples.
     347
     348* **Dependency preservation:** FD06 is fully contained in ARTIST, so {{{artist_id → artist_name, artist_description, artist_photo}}} remains directly enforceable.
     349
     350
     351==== 3. SONG(song_id, song_name, song_duration)
     352
     353{{{
     354song_id → song_name, song_duration
     355}}}
     356
     357Since {{{song_id}}} is a proper subset of K, this is a partial dependency.
     358
     359{{{
     360R3 = R2 - {song_name, song_duration}
     361
     362R3 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_id, admin_type, discount_percentage,
     363      points_collected, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     364      purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount, wishlist_id, quantity,
     365      price_at_purchase, added_at, release_ordinal, type, song_ordinal}
     366}}}
     367
     368* **Lossless join:** SONG and R3 intersect on {{{song_id}}}. Since {{{song_id → song_name, song_duration}}}, the common attribute determines the complete SONG relation. The decomposition is therefore lossless.
     369
     370* **Dependency preservation:** FD08 is preserved entirely in SONG and can be checked without performing a join.
     371
     372
     373==== 4. ADMIN(admin_id, admin_type, discount_percentage)
     374
     375ADMIN is extracted before MODIFICATION because {{{admin_id}}} is needed here and will later be removed from the residual relation when FD11 is decomposed.
     376
     377{{{
     378admin_id → admin_type, discount_percentage
     379}}}
     380
     381Furthermore:
     382
     383{{{
     384modification_id → admin_id
     385}}}
     386
     387and {{{modification_id}}} is a proper subset of K. Therefore the admin attributes are ultimately determined by a proper subset of K.
     388
     389{{{
     390R4 = R3 - {admin_type, discount_percentage}
     391
     392R4 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_id, points_collected, artist_id, release_id,
     393      album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method, purchase_date, points_earned, points_used,
     394      status, modification_id, date_modified, type_of_modification, discount, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal,
     395      type, song_ordinal}
     396}}}
     397
     398* **Lossless join:** ADMIN and R4 intersect on {{{admin_id}}}. Since {{{admin_id → admin_type, discount_percentage}}}, the common attribute determines the whole ADMIN relation, making the decomposition lossless.
     399
     400* **Dependency preservation:** FD04 is fully contained in ADMIN and therefore remains directly enforceable.
     401
     402
     403==== 5. CONSUMER(user_id, points_collected)
     404
     405{{{
     406user_id → points_collected
     407}}}
     408
     409Since:
     410
     411{{{
     412order_id → user_id
     413}}}
     414
     415and {{{order_id}}} is a proper subset of K, {{{points_collected}}} is indirectly dependent on only part of K.
     416
     417{{{
     418R5 = R4 - {points_collected}
     419
     420R5 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_id, artist_id, release_id, album_id, song_id,
     421      product_id, format, price, product_description, stock, order_id, payment_method, purchase_date, points_earned, points_used, status,
     422      modification_id, date_modified, type_of_modification, discount, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal, type,
     423      song_ordinal}
     424}}}
     425
     426* **Lossless join:** CONSUMER and R5 intersect on {{{user_id}}}. Since {{{user_id → points_collected}}}, the shared attribute determines all of CONSUMER.
     427
     428* **Dependency preservation:** FD05 is preserved directly in CONSUMER.
     429
     430
     431==== 6. USER(user_id, email, username, password, date_created, shipping_address, telephone_number)
     432
     433USER is extracted before ORDER because ORDER will later remove {{{user_id}}} from the residual relation.
     434
     435{{{
     436user_id → email, username, password, date_created, shipping_address, telephone_number
     437email → user_id
     438username → user_id
     439}}}
     440
     441Because {{{order_id → user_id}}} and {{{order_id}}} is a proper subset of K, the USER attributes are also ultimately determined by a proper subset of K.
     442
     443{{{
     444R6 = R5 - {email, username, password, date_created, shipping_address, telephone_number}
     445
     446R6 = {user_id, admin_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     447      purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount, wishlist_id, quantity,
     448      price_at_purchase, added_at, release_ordinal, type, song_ordinal}
     449}}}
     450
     451* **Lossless join:** USER and R6 intersect on {{{user_id}}}. Since {{{user_id}}} determines every other attribute of USER, the decomposition is lossless.
     452
     453* **Dependency preservation:** FD01, FD02 and FD03 are all contained in USER. Therefore both the primary identifier {{{user_id}}} and the alternate candidate keys {{{email}}} and {{{username}}} retain their functional dependencies.
     454
     455
     456==== 7. ORDER_PRODUCTS(order_id, product_id, price_at_purchase, quantity)
     457
     458{{{
     459(order_id, product_id) → price_at_purchase, quantity
     460}}}
     461
     462The determinant {{{(order_id, product_id)}}} is a proper subset of K, so the dependency is partial.
     463
     464{{{
     465R7 = R6 - {price_at_purchase, quantity}
     466
     467R7 = {user_id, admin_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     468      purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount, wishlist_id, added_at,
    334469      release_ordinal, type, song_ordinal}
    335470}}}
    336471
    337 * **Lossless join:** The original relation can be reconstructed through a join using {{{song_id}}}.
    338 
    339 * **Dependency preservation:** The dependency {{{song_id → song_name, song_duration}}} is preserved in the new ''SONG'' relation.
    340 
    341 ==== 5. MODIFICATION(modification_id, admin_id, date_modified, type_of_modification, discount)
    342 
    343 {{{
    344 R5 = R4 - {admin_id, date_modified, type_of_modification, discount}
    345 
    346 R5 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_type, discount_percentage, points_collected,
    347       artist_id, release_id, album_id, song_id, product_id, order_id, payment_method, purchase_date, points_earned, points_used, status,
    348       modification_id, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal, type, song_ordinal}
    349 }}}
    350 
    351 * **Lossless join:** The original relation can be reconstructed through a join using {{{modification_id}}}.
    352 
    353 * **Dependency preservation:** The dependency {{{modification_id → admin_id, date_modified, type_of_modification, discount}}} is preserved in the new ''MODIFICATION'' relation.
    354 
    355 ==== 6. ORDER(order_id, user_id, payment_method, purchase_date, points_earned, points_used, status)
    356 
    357 {{{
    358 R6 = R5 - {payment_method, purchase_date, points_earned, points_used, status}
    359 
    360 R6 = {user_id, email, username, password, date_created, shipping_address, telephone_number, admin_type, discount_percentage, points_collected,
    361       artist_id, release_id, album_id, song_id, product_id, order_id, modification_id, wishlist_id, quantity, price_at_purchase, added_at,
     472* **Lossless join:** ORDER_PRODUCTS and R7 intersect on {{{order_id, product_id}}}. This pair determines {{{price_at_purchase}}} and {{{quantity}}}, so the common attributes determine the complete ORDER_PRODUCTS relation. The decomposition is therefore lossless.
     473
     474* **Dependency preservation:** FD14 remains entirely inside ORDER_PRODUCTS.
     475
     476
     477==== 8. WISHLIST_PRODUCTS(wishlist_id, product_id, added_at)
     478
     479This relation must be created before WISHLIST removes {{{wishlist_id}}} from the residual relation.
     480
     481{{{
     482(wishlist_id, product_id) → added_at
     483}}}
     484
     485Because {{{order_id → user_id → wishlist_id}}}, and both {{{order_id}}} and {{{product_id}}} belong to a proper subset of K, the determinant can ultimately be obtained from part of the candidate key.
     486
     487{{{
     488R8 = R7 - {added_at}
     489
     490R8 = {user_id, admin_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     491      purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount, wishlist_id,
    362492      release_ordinal, type, song_ordinal}
    363493}}}
    364494
    365 * **Lossless join:** The original relation can be reconstructed through a join using {{{order_id}}}.
    366 
    367 * **Dependency preservation:** The dependency {{{order_id → user_id, payment_method, purchase_date, points_earned, points_used, status}}} is preserved in the new ''ORDER'' relation.
    368 
    369 ==== 7. USER(user_id, email, username, password, date_created, shipping_address, telephone_number)
    370 
    371 {{{
    372 R7 = R6 - {email, username, password, date_created, shipping_address, telephone_number}
    373 
    374 R7 = {user_id, admin_type, discount_percentage, points_collected, artist_id, release_id, album_id, song_id, product_id, order_id,
    375       modification_id, wishlist_id, quantity, price_at_purchase, added_at, release_ordinal, type, song_ordinal}
    376 }}}
    377 
    378 * **Lossless join:** The original relation can be reconstructed through a join using {{{user_id}}}.
    379 
    380 * **Dependency preservation:** The dependency {{{user_id → email, username, password, date_created, shipping_address, telephone_number}}} is preserved in the new ''USER'' relation.
    381 
    382 ==== 8. ORDER_PRODUCTS(order_id, product_id, price_at_purchase, quantity)
    383 
    384 {{{
    385 R8 = R7 - {price_at_purchase, quantity}
    386 
    387 R8 = {user_id, admin_type, discount_percentage, points_collected, artist_id, release_id, album_id, song_id, product_id, order_id,
    388       modification_id, wishlist_id, added_at, release_ordinal, type, song_ordinal}
    389 }}}
    390 
    391 * **Lossless join:** The original relation can be reconstructed through a join using {{{order_id, product_id}}}.
    392 
    393 * **Dependency preservation:** The dependency {{{(order_id, product_id) → price_at_purchase, quantity}}} is preserved in the new ''ORDER_PRODUCTS'' relation.
    394 
    395 ==== 9. WISHLIST_PRODUCTS(wishlist_id, product_id, added_at)
    396 
    397 {{{
    398 R9 = R8 - {added_at}
    399 
    400 R9 = {user_id, admin_type, discount_percentage, points_collected, artist_id, release_id, album_id, song_id, product_id, order_id,
    401       modification_id, wishlist_id, release_ordinal, type, song_ordinal}
    402 }}}
    403 
    404 * **Lossless join:** The original relation can be reconstructed through a join using {{{wishlist_id, product_id}}}.
    405 
    406 * **Dependency preservation:** The dependency {{{(wishlist_id, product_id) → added_at}}} is preserved in the new ''WISHLIST_PRODUCTS'' relation.
    407 
    408 ==== 10. RELEASE_ARTISTS(release_id, artist_id, release_ordinal, type)
    409 
    410 {{{
    411 R10 = R9 - {release_ordinal, type}
    412 
    413 R10 = {user_id, admin_type, discount_percentage, points_collected, artist_id, release_id, album_id, song_id, product_id, order_id,
    414        modification_id, wishlist_id, song_ordinal}
    415 }}}
    416 
    417 * **Lossless join:** The original relation can be reconstructed through a join using {{{release_id, artist_id}}}.
    418 
    419 * **Dependency preservation:** The dependency {{{(release_id, artist_id) → release_ordinal, type}}} is preserved in the new ''RELEASE_ARTISTS'' relation.
    420 
    421 ==== 11. SONG_ARTISTS(song_id, artist_id, song_ordinal)
    422 
    423 {{{
    424 R11 = R10 - {song_ordinal}
    425 
    426 R11 = {user_id, admin_type, discount_percentage, points_collected, artist_id, release_id, album_id, song_id, product_id, order_id,
    427        modification_id, wishlist_id}
    428 }}}
    429 
    430 * **Lossless join:** The original relation can be reconstructed through a join using {{{song_id, artist_id}}}.
    431 
    432 * **Dependency preservation:** The dependency {{{(song_id, artist_id) → song_ordinal}}} is preserved in the new ''SONG_ARTISTS'' relation.
    433 
    434 ==== 12. ADMIN(user_id, admin_type, discount_percentage)
    435 
    436 {{{
    437 R12 = R11 - {admin_type, discount_percentage}
    438 
    439 R12 = {user_id, points_collected, artist_id, release_id, album_id, song_id, product_id, order_id, modification_id, wishlist_id}
    440 }}}
    441 
    442 * **Lossless join:** The original relation can be reconstructed through a join using {{{user_id}}}.
    443 
    444 * **Dependency preservation:** The dependency {{{user_id → admin_type, discount_percentage}}} is preserved in the new ''ADMIN'' relation.
    445 
    446 ==== 13. CONSUMER(user_id, points_collected)
    447 
    448 {{{
    449 R13 = R12 - {points_collected}
    450 
    451 R13 = {user_id, artist_id, release_id, album_id, song_id, product_id, order_id, modification_id, wishlist_id}
    452 }}}
    453 
    454 * **Lossless join:** The original relation can be reconstructed through a join using {{{user_id}}}.
    455 
    456 * **Dependency preservation:** The dependency {{{user_id → points_collected}}} is preserved in the new ''CONSUMER'' relation.
    457 
    458 ==== 14. WISHLIST(user_id, wishlist_id)
    459 
    460 {{{
    461 R14 = R13 - {wishlist_id}
    462 
    463 R14 = {user_id, artist_id, release_id, album_id, song_id, product_id, order_id, modification_id}
    464 }}}
    465 
    466 * **Lossless join:** The original relation can be reconstructed through a join using {{{user_id}}}.
    467 
    468 * **Dependency preservation:** The dependencies {{{user_id → wishlist_id}}} and {{{wishlist_id → user_id}}} are preserved in the new ''WISHLIST'' relation.
    469 
    470 ==== 15. Removing Remaining Partial Dependencies
    471 
    472 Two non-prime attributes remain:
    473 
    474 1. {{{order_id → user_id}}}
    475 2. {{{product_id → release_id}}}
    476 
    477 Since {{{order_id}}} and {{{product_id}}} are proper subsets of the candidate key, these are still partial dependencies. However, these dependencies are already represented in ''ORDER'' and ''PRODUCT''.
    478 
    479 {{{
    480 R15 = R14 - {user_id, release_id}
    481 
    482 R15 = {artist_id, release_id, album_id, song_id, product_id,
    483        order_id, modification_id}
    484 }}}
    485 
    486 * **Lossless join:** The removed {{{user_id}}} can be recovered through the existing ''ORDER'' relation using {{{order_id}}} and the removed {{{release_id}}} can be recovered through the existing ''PRODUCT'' relation using {{{product_id}}}.
    487 
    488 * **Dependency preservation:** The dependency {{{order_id → user_id}}} remains preserved in the existing ''ORDER'' relation and the dependency {{{product_id → release_id}}} remains preserved in the existing ''PRODUCT'' relation.
    489 
    490 }}}
     495* **Lossless join:** WISHLIST_PRODUCTS and R8 intersect on {{{wishlist_id, product_id}}}. These attributes determine {{{added_at}}}, so the common attributes determine the full WISHLIST_PRODUCTS relation.
     496
     497* **Dependency preservation:** FD15 is preserved entirely inside WISHLIST_PRODUCTS.
     498
     499
     500==== 9. RELEASE_ARTISTS(release_id, artist_id, release_ordinal, type)
     501
     502This relation is extracted before PRODUCT because PRODUCT will later remove {{{release_id}}} from the residual relation.
     503
     504{{{
     505(release_id, artist_id) → release_ordinal, type
     506}}}
     507
     508Since {{{product_id → release_id}}}, the pair {{{(product_id, artist_id)}}}, which is a proper subset of K, can determine these attributes.
     509
     510{{{
     511R9 = R8 - {release_ordinal, type}
     512
     513R9 = {user_id, admin_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     514      purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount, wishlist_id, song_ordinal}
     515}}}
     516
     517* **Lossless join:** RELEASE_ARTISTS and R9 intersect on {{{release_id, artist_id}}}. This composite determinant determines {{{release_ordinal}}} and {{{type}}}, so the decomposition is lossless.
     518
     519* **Dependency preservation:** FD16 is fully contained in RELEASE_ARTISTS.
     520
     521
     522==== 10. SONG_ARTISTS(song_id, artist_id, song_ordinal)
     523
     524{{{
     525(song_id, artist_id) → song_ordinal
     526}}}
     527
     528The determinant {{{(song_id, artist_id)}}} is a proper subset of K.
     529
     530{{{
     531R10 = R9 - {song_ordinal}
     532
     533R10 = {user_id, admin_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     534       purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount, wishlist_id}
     535}}}
     536
     537* **Lossless join:** SONG_ARTISTS and R10 intersect on {{{song_id, artist_id}}}. Since the pair determines {{{song_ordinal}}}, it determines the entire SONG_ARTISTS relation.
     538
     539* **Dependency preservation:** FD17 remains directly represented inside SONG_ARTISTS.
     540
     541
     542==== 11. WISHLIST(user_id, wishlist_id)
     543
     544The following two dependencies hold:
     545
     546{{{
     547wishlist_id → user_id
     548user_id → wishlist_id
     549}}}
     550
     551WISHLIST is decomposed only after WISHLIST_PRODUCTS because {{{wishlist_id}}} will now be removed from the residual relation.
     552
     553{{{
     554R11 = R10 - {wishlist_id}
     555
     556R11 = {user_id, admin_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     557       purchase_date, points_earned, points_used, status, modification_id, date_modified, type_of_modification, discount}
     558}}}
     559
     560* **Lossless join:** WISHLIST and R11 intersect on {{{user_id}}}. Since {{{user_id → wishlist_id}}}, {{{user_id}}} determines the complete WISHLIST relation. Therefore the split is lossless.
     561
     562* **Dependency preservation:** Both FD12 and FD13 remain inside WISHLIST, since both {{{user_id}}} and {{{wishlist_id}}} are contained in the same relation.
     563
     564
     565==== 12. MODIFICATION(modification_id, admin_id, date_modified, type_of_modification, discount)
     566
     567ADMIN has already been extracted, so {{{admin_id}}} can now safely be removed from the residual relation.
     568
     569{{{
     570modification_id → admin_id, date_modified, type_of_modification, discount
     571}}}
     572
     573Since {{{modification_id}}} is a proper subset of K, this is a partial dependency.
     574
     575{{{
     576R12 = R11 - {admin_id, date_modified, type_of_modification, discount}
     577
     578R12 = {user_id, artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, payment_method,
     579       purchase_date, points_earned, points_used, status, modification_id}
     580}}}
     581
     582* **Lossless join:** MODIFICATION and R12 intersect on {{{modification_id}}}. Since {{{modification_id}}} determines all remaining MODIFICATION attributes, the original information can be reconstructed without spurious tuples.
     583
     584* **Dependency preservation:** FD11 is preserved entirely inside MODIFICATION. FD04 has already been preserved separately inside ADMIN.
     585
     586
     587==== 13. ORDER(order_id, user_id, payment_method, purchase_date, points_earned, points_used, status)
     588
     589USER, CONSUMER and WISHLIST have already been extracted, so {{{user_id}}} can now be removed from the residual relation.
     590
     591{{{
     592order_id → user_id, payment_method, purchase_date, points_earned, points_used, status
     593}}}
     594
     595Since {{{order_id}}} is a proper subset of K, this is a partial dependency.
     596
     597{{{
     598R13 = R12 - {user_id, payment_method, purchase_date, points_earned, points_used, status}
     599
     600R13 = {artist_id, release_id, album_id, song_id, product_id, format, price, product_description, stock, order_id, modification_id}
     601}}}
     602
     603* **Lossless join:** ORDER and R13 intersect on {{{order_id}}}. Since {{{order_id}}} determines all attributes of ORDER, the decomposition is lossless.
     604
     605* **Dependency preservation:** FD10 is fully preserved inside ORDER. The dependencies involving {{{user_id}}} have already been preserved in USER, CONSUMER and WISHLIST before {{{user_id}}} was removed from the residual relation.
     606
     607
     608==== 14. PRODUCT(product_id, release_id, format, price, product_description, stock)
     609
     610PRODUCT is decomposed last among the identifier-bearing relations because {{{release_id}}} was needed earlier for RELEASE and RELEASE_ARTISTS.
     611
     612{{{
     613product_id → release_id, format, price, product_description, stock
     614}}}
     615
     616Since {{{product_id}}} is a proper subset of K, this is a partial dependency.
     617
     618{{{
     619R14 = R13 - {release_id, format, price, product_description, stock}
     620
     621R14 = {artist_id, album_id, song_id, product_id, order_id, modification_id}
     622}}}
     623
     624* **Lossless join:** PRODUCT and R14 intersect on {{{product_id}}}. Since {{{product_id}}} determines {{{release_id, format, price, product_description, stock}}}, the shared attribute determines the entire PRODUCT relation. Therefore the decomposition is lossless.
     625
     626* **Dependency preservation:** FD09 is fully contained inside PRODUCT. The dependency involving {{{release_id}}} has already been preserved in RELEASE and RELEASE_ARTISTS before {{{release_id}}} was removed from the residual relation.
     627
     628
     629==== Residual Relation
     630
     631After all partial dependencies have been removed, the residual relation is:
     632
     633{{{
     634R14 = {artist_id, album_id, song_id, product_id, order_id, modification_id}
     635}}}
     636
     637This residual relation consists only of attributes belonging to the candidate key:
     638
     639{{{
     640K = {order_id, product_id, artist_id, song_id, modification_id, album_id}
     641}}}
     642
     643Therefore there are no non-prime attributes left in R14 that can be partially dependent on a proper subset of the candidate key.
     644
     645Consequently, the decomposition has removed all partial dependencies from the universal relation and the resulting relations satisfy 2NF.
    491646
    492647== 3NF Decomposition
    … …  
    495650Listed bellow are the relations obtained after the 2NF decomposition as they are examined for transitive dependencies to determine whether or not a 3NF Decomposition is needed.
    496651
    497 ==== PRODUCT
    498 {{{
    499 Attributes : product_id, release_id, format, price, product_description, stock
    500 FDs        : FD09 (product_id → release_id, format, price, product_description, stock)
    501 CKs / PK   : {product_id}
    502 }}}
    503 {{{release_id}}} is a non-key attribute and a foreign key to RELEASE, but it does not determine any other attribute within PRODUCT. All non-key attributes depend directly on {{{product_id}}}. **No decomposition needed**.
     652==== RELEASE
     653{{{
     654Attributes : release_id, title, record_label, genre, release_date, cover_photo, duration
     655FDs        : FD07 (release_id → title, record_label, genre, release_date, cover_photo, duration)
     656CKs / PK   : {release_id}
     657}}}
     658All non-key attributes depend directly on {{{release_id}}}. There is no non-key attribute that determines another non-key attribute within RELEASE. Therefore, no transitive dependency exists. **No decomposition needed**.
    504659
    505660==== ARTIST
    … …  
    511666All non-key attributes depend directly on {{{artist_id}}}. There are no dependencies between non-key attributes. **No decomposition needed**.
    512667
    513 ==== RELEASE
    514 {{{
    515 Attributes : release_id, title, record_label, genre, release_date, cover_photo, duration
    516 FDs        : FD07 (release_id → title, record_label, genre, release_date, cover_photo, duration)
    517 CKs / PK   : {release_id}
    518 }}}
    519 All non-key attributes depend directly on {{{release_id}}}. There is no non-key attribute that determines another non-key attribute. **No decomposition needed**.
    520 
    521668==== SONG
    522669{{{
    … …  
    525672CKs / PK   : {song_id}
    526673}}}
    527 Only two non-key attributes exist, and both depend directly on {{{song_id}}}. No transitive dependency exists. **No decomposition needed**.
    528 
    529 ==== MODIFICATION
    530 {{{
    531 Attributes : modification_id, admin_id, date_modified, type_of_modification, discount
    532 FDs        : FD11 (modification_id → admin_id, date_modified, type_of_modification, discount)
    533 CKs / PK   : {modification_id}
    534 }}}
    535 {{{admin_id}}} is a non-key attribute and a foreign key to ADMIN. Although {{{admin_id}}} determines attributes in ADMIN, it does not determine any other attribute inside MODIFICATION. Therefore, no transitive dependency exists within this relation. **No decomposition needed**.
    536 
    537 ==== ORDER
    538 {{{
    539 Attributes : order_id, user_id, payment_method, purchase_date, points_earned, points_used, status
    540 FDs        : FD10 (order_id → user_id, payment_method, purchase_date, points_earned, points_used, status)
    541 CKs / PK   : {order_id}
    542 }}}
    543 {{{user_id}}} is a non-key foreign key to USER, but it does not determine any other attribute within ORDER. All non-key attributes depend directly on {{{order_id}}}. **No decomposition needed**.
     674Both non-key attributes depend directly on {{{song_id}}}. Neither non-key attribute determines another attribute within the relation. Therefore, no transitive dependency exists. **No decomposition needed**.
     675
     676==== ADMIN
     677{{{
     678Attributes : admin_id, admin_type, discount_percentage
     679FDs        : FD04 (admin_id → admin_type, discount_percentage)
     680CKs / PK   : {admin_id}
     681}}}
     682Both non-key attributes depend directly on {{{admin_id}}}. Neither {{{admin_type}}} nor {{{discount_percentage}}} determines another attribute within ADMIN. Therefore, there is no transitive dependency. **No decomposition needed**.
     683
     684==== CONSUMER
     685{{{
     686Attributes : user_id, points_collected
     687FDs        : FD05 (user_id → points_collected)
     688CKs / PK   : {user_id}
     689}}}
     690There is only one non-key attribute, {{{points_collected}}}, and it depends directly on the candidate key {{{user_id}}}. Therefore, no transitive dependency is possible. **No decomposition needed**.
    544691
    545692==== USER
    … …  
    552699PK         : user_id
    553700}}}
    554 {{{email}}} and {{{username}}} both determine {{{user_id}}}, but each is itself a complete candidate key. Therefore, neither creates a transitive dependency. Every determinant in the listed functional dependencies is a candidate key. **No decomposition needed**.
     701{{{email}}} and {{{username}}} both determine {{{user_id}}}, but each is itself a complete candidate key. Therefore, neither dependency represents a dependency from a non-key attribute to another non-key attribute. Every determinant in the listed functional dependencies is a candidate key and therefore a superkey. **No decomposition needed**.
    555702
    556703==== ORDER_PRODUCTS
    … …  
    560707CKs / PK   : {order_id, product_id}
    561708}}}
    562 The determinant {{{(order_id, product_id)}}} is the complete composite candidate key. Neither {{{order_id}}} nor {{{product_id}}} determines either non-key attribute independently within this relation. No transitive dependency exists. **No decomposition needed**.
     709The determinant {{{(order_id, product_id)}}} is the complete composite candidate key. Both non-key attributes, {{{price_at_purchase}}} and {{{quantity}}}, depend directly on the complete key. Neither {{{order_id}}} nor {{{product_id}}} determines either non-key attribute independently within this relation, and neither non-key attribute determines another non-key attribute. Therefore, no transitive dependency exists. **No decomposition needed**.
    563710
    564711==== WISHLIST_PRODUCTS
    … …  
    568715CKs / PK   : {wishlist_id, product_id}
    569716}}}
    570 The only non-key attribute, {{{added_at}}}, depends directly on the complete composite candidate key. There are no other non-key attributes that could create a transitive dependency. **No decomposition needed**.
     717The only non-key attribute, {{{added_at}}}, depends directly on the complete composite candidate key {{{(wishlist_id, product_id)}}}. There are no other non-key attributes that could form a transitive dependency. **No decomposition needed**.
    571718
    572719==== RELEASE_ARTISTS
    … …  
    576723CKs / PK   : {release_id, artist_id}
    577724}}}
    578 Both non-key attributes depend directly on the complete composite candidate key {{{(release_id, artist_id)}}}. Neither non-key attribute determines the other. **No decomposition needed**.
     725Both non-key attributes depend directly on the complete composite candidate key {{{(release_id, artist_id)}}}. Neither {{{release_ordinal}}} nor {{{release_artist_type}}} determines another attribute within the relation. Therefore, no transitive dependency exists. **No decomposition needed**.
    579726
    580727==== SONG_ARTISTS
    … …  
    584731CKs / PK   : {song_id, artist_id}
    585732}}}
    586 {{{song_ordinal}}} depends directly on the complete composite candidate key. There are no other non-key attributes and therefore no transitive dependency. **No decomposition needed**.
    587 ==== ADMIN
    588 {{{
    589 Attributes : user_id, admin_type, discount_percentage
    590 FDs        : FD04 (user_id → admin_type, discount_percentage)
    591 CKs / PK   : {user_id}
    592 }}}
    593 Both non-key attributes depend directly on **user_id**. Neither {{{admin_type}}} nor {{{discount_percentage}}} determines another attribute within the relation. **No decomposition needed**.
    594 ==== CONSUMER
    595 {{{
    596 Attributes : user_id, points_collected
    597 FDs        : FD05 (user_id → points_collected)
    598 CKs / PK   : {user_id}
    599 }}}
    600 There is only one non-key attribute, and it depends directly on the candidate key. No transitive dependency is possible. **No decomposition needed**.
     733{{{song_ordinal}}} depends directly on the complete composite candidate key {{{(song_id, artist_id)}}}. There are no other non-key attributes and therefore no transitive dependency. **No decomposition needed**.
     734
    601735==== WISHLIST
    602736{{{
    … …  
    607741PK         : wishlist_id
    608742}}}
    609 {{{user_id}}} and {{{wishlist_id}}} determine each other, meaning each attribute is independently a candidate key. Both determinants are therefore superkeys, and no transitive dependency exists. **No decomposition needed**.
    610 }}}
     743{{{user_id}}} and {{{wishlist_id}}} determine each other, meaning that each attribute is independently a candidate key. Consequently, both determinants are superkeys. There is no dependency whose determinant is a non-key attribute, and therefore no transitive dependency exists. **No decomposition needed**.
     744
     745==== MODIFICATION
     746{{{
     747Attributes : modification_id, admin_id, date_modified, type_of_modification, discount
     748FDs        : FD11 (modification_id → admin_id, date_modified, type_of_modification, discount)
     749CKs / PK   : {modification_id}
     750}}}
     751{{{admin_id}}} is a non-key attribute and a foreign key to ADMIN. Although {{{admin_id}}} determines {{{admin_type}}} and {{{discount_percentage}}} in the separate ADMIN relation, those attributes are not present inside MODIFICATION. Within MODIFICATION, no non-key attribute determines another non-key attribute. All non-key attributes depend directly on {{{modification_id}}}. Therefore, no transitive dependency exists within this relation. **No decomposition needed**.
     752
     753==== ORDER
     754{{{
     755Attributes : order_id, user_id, payment_method, purchase_date, points_earned, points_used, status
     756FDs        : FD10 (order_id → user_id, payment_method, purchase_date, points_earned, points_used, status)
     757CKs / PK   : {order_id}
     758}}}
     759{{{user_id}}} is a non-key attribute and a foreign key to USER. Although {{{user_id}}} determines attributes in USER, CONSUMER and WISHLIST, those attributes are stored in separate relations and are not present inside ORDER. Within ORDER, every non-key attribute depends directly on {{{order_id}}}, and no non-key attribute determines another non-key attribute. **No decomposition needed**.
     760
     761==== PRODUCT
     762{{{
     763Attributes : product_id, release_id, format, price, product_description, stock
     764FDs        : FD09 (product_id → release_id, format, price, product_description, stock)
     765CKs / PK   : {product_id}
     766}}}
     767{{{release_id}}} is a non-key attribute and a foreign key to RELEASE. Although {{{release_id}}} determines attributes in RELEASE, those attributes are no longer contained within PRODUCT after the 2NF decomposition. Therefore, {{{release_id}}} does not determine another non-key attribute within PRODUCT. All non-key attributes depend directly on {{{product_id}}}. **No decomposition needed**.
     768
     769==== R14
     770{{{
     771Attributes : artist_id, album_id, song_id, product_id, order_id, modification_id
     772FDs        : No non-trivial functional dependencies hold within R14 under the current FD set.
     773CKs / PK   : {artist_id, album_id, song_id, product_id, order_id, modification_id}
     774}}}
     775R14 contains only attributes of the candidate key of the original universal relation. There are no non-key attributes and no non-trivial functional dependency in R14 whose determinant is not a superkey. Therefore, no transitive dependency can exist. **No decomposition needed**.
     776
     777Since none of the relations resulting from the 2NF decomposition contains a transitive dependency from a key through a non-key attribute to another non-key attribute, no additional decomposition is required to achieve Third Normal Form.
     778
     779Therefore, all relations obtained after the 2NF decomposition already satisfy 3NF.
    611780
    612781== BCNF Decomposition
    … …  
    615784Listed below are the relations obtained after the 3NF analysis, examined to determine whether every non-trivial functional dependency has a superkey as its determinant and whether further decomposition is required to achieve BCNF.
    616785
     786A relation satisfies BCNF if, for every non-trivial functional dependency {{{X → Y}}}, the determinant {{{X}}} is a superkey of that relation.
     787
    617788The primary keys are bolded.
    618789
    619 1. PRODUCT(**product_id**, release_id, format, price, product_description, stock) → **satisfies BCNF**
    620 2. ARTIST(**artist_id**, artist_name, artist_description, artist_photo) → satisfies BCNF
    621 3. RELEASE(**release_id**, title, record_label, genre, release_date, cover_photo, duration) → **satisfies BCNF**
    622 4. SONG(**song_id**, song_name, song_duration) → satisfies BCNF
    623 5. MODIFICATION(**modification_id**, admin_id, date_modified, type_of_modification, discount) → **satisfies BCNF**
    624 6. ORDER(**order_id**, user_id, payment_method, purchase_date, points_earned, points_used, status) → **satisfies BCNF**
    625 7. USER(**user_id**, email, username, password, date_created, shipping_address, telephone_number) → **satisfies BCNF**
    626 8. ORDER_PRODUCTS(**order_id**, **product_id**, price_at_purchase, quantity) → **satisfies BCNF**
    627 9. WISHLIST_PRODUCTS(**wishlist_id**, **product_id**, added_at) → **satisfies BCNF**
    628 10. RELEASE_ARTISTS(**release_id**, **artist_id**, release_ordinal, release_artist_type) → **satisfies BCNF**
    629 11. SONG_ARTISTS(**song_id**, **artist_id**, song_ordinal) → **satisfies BCNF**
    630 12. ADMIN(**user_id**, admin_type, discount_percentage) → **satisfies BCNF**
    631 13. CONSUMER(**user_id**, points_collected) → **satisfies BCNF**
    632 14. WISHLIST(**wishlist_id**, user_id) → **satisfies BCNF**
    633 15. R15 = {**artist_id**, **album_id**, **song_id**, **product_id**, **order_id**, **modification_id**} → **satisfies BCNF**
     7901. RELEASE(**release_id**, title, record_label, genre, release_date, cover_photo, duration) → **satisfies BCNF**
     791
     792   The only non-trivial functional dependency is {{{release_id → title, record_label, genre, release_date, cover_photo, duration}}}. Since {{{release_id}}} is the primary key and therefore a superkey, RELEASE satisfies BCNF.
     793
     7942. ARTIST(**artist_id**, artist_name, artist_description, artist_photo) → **satisfies BCNF**
     795
     796   The only non-trivial functional dependency is {{{artist_id → artist_name, artist_description, artist_photo}}}. Since {{{artist_id}}} is the primary key and therefore a superkey, ARTIST satisfies BCNF.
     797
     7983. SONG(**song_id**, song_name, song_duration) → **satisfies BCNF**
     799
     800   The only non-trivial functional dependency is {{{song_id → song_name, song_duration}}}. Since {{{song_id}}} is the primary key and therefore a superkey, SONG satisfies BCNF.
     801
     8024. ADMIN(**admin_id**, admin_type, discount_percentage) → **satisfies BCNF**
     803
     804   The only non-trivial functional dependency is {{{admin_id → admin_type, discount_percentage}}}. Since {{{admin_id}}} is the primary key and therefore a superkey, ADMIN satisfies BCNF.
     805
     8065. CONSUMER(**user_id**, points_collected) → **satisfies BCNF**
     807
     808   The only non-trivial functional dependency is {{{user_id → points_collected}}}. Since {{{user_id}}} is the primary key and therefore a superkey, CONSUMER satisfies BCNF.
     809
     8106. USER(**user_id**, email, username, password, date_created, shipping_address, telephone_number) → **satisfies BCNF**
     811
     812   The relevant functional dependencies are:
     813
     814   {{{
     815   user_id → email, username, password, date_created, shipping_address, telephone_number
     816   email → user_id
     817   username → user_id
     818   }}}
     819
     820   {{{user_id}}}, {{{email}}}, and {{{username}}} are all candidate keys of USER. Therefore, every determinant in a non-trivial functional dependency is a superkey, so USER satisfies BCNF.
     821
     8227. ORDER_PRODUCTS(**order_id**, **product_id**, price_at_purchase, quantity) → **satisfies BCNF**
     823
     824   The non-trivial functional dependency is {{{(order_id, product_id) → price_at_purchase, quantity}}}. The determinant {{{(order_id, product_id)}}} is the complete composite primary key and therefore a superkey. ORDER_PRODUCTS satisfies BCNF.
     825
     8268. WISHLIST_PRODUCTS(**wishlist_id**, **product_id**, added_at) → **satisfies BCNF**
     827
     828   The non-trivial functional dependency is {{{(wishlist_id, product_id) → added_at}}}. The determinant {{{(wishlist_id, product_id)}}} is the complete composite primary key and therefore a superkey. WISHLIST_PRODUCTS satisfies BCNF.
     829
     8309. RELEASE_ARTISTS(**release_id**, **artist_id**, release_ordinal, release_artist_type) → **satisfies BCNF**
     831
     832   The non-trivial functional dependency is {{{(release_id, artist_id) → release_ordinal, release_artist_type}}}. The determinant {{{(release_id, artist_id)}}} is the complete composite primary key and therefore a superkey. RELEASE_ARTISTS satisfies BCNF.
     833
     83410. SONG_ARTISTS(**song_id**, **artist_id**, song_ordinal) → **satisfies BCNF**
     835
     836   The non-trivial functional dependency is {{{(song_id, artist_id) → song_ordinal}}}. The determinant {{{(song_id, artist_id)}}} is the complete composite primary key and therefore a superkey. SONG_ARTISTS satisfies BCNF.
     837
     83811. WISHLIST(**wishlist_id**, user_id) → **satisfies BCNF**
     839
     840   The relevant functional dependencies are:
     841
     842   {{{
     843   wishlist_id → user_id
     844   user_id → wishlist_id
     845   }}}
     846
     847   Both {{{wishlist_id}}} and {{{user_id}}} are candidate keys of WISHLIST. Therefore, both determinants are superkeys and WISHLIST satisfies BCNF.
     848
     84912. MODIFICATION(**modification_id**, admin_id, date_modified, type_of_modification, discount) → **satisfies BCNF**
     850
     851   The only non-trivial functional dependency within MODIFICATION is {{{modification_id → admin_id, date_modified, type_of_modification, discount}}}. Since {{{modification_id}}} is the primary key and therefore a superkey, MODIFICATION satisfies BCNF.
     852
     85313. ORDER(**order_id**, user_id, payment_method, purchase_date, points_earned, points_used, status) → **satisfies BCNF**
     854
     855   The only non-trivial functional dependency within ORDER is {{{order_id → user_id, payment_method, purchase_date, points_earned, points_used, status}}}. Since {{{order_id}}} is the primary key and therefore a superkey, ORDER satisfies BCNF.
     856
     85714. PRODUCT(**product_id**, release_id, format, price, product_description, stock) → **satisfies BCNF**
     858
     859   The only non-trivial functional dependency within PRODUCT is {{{product_id → release_id, format, price, product_description, stock}}}. Since {{{product_id}}} is the primary key and therefore a superkey, PRODUCT satisfies BCNF.
     860
     86115. R14 = {**artist_id**, **album_id**, **song_id**, **product_id**, **order_id**, **modification_id**} → **satisfies BCNF**
     862
     863   R14 contains only the attributes of the candidate key remaining after the 2NF decomposition. Under the current set of functional dependencies, there are no non-trivial functional dependencies within R14 whose determinant is not a superkey. Therefore, R14 satisfies BCNF.
     864
     865Since every non-trivial functional dependency in every relation has a superkey as its determinant, all relations obtained after the 3NF analysis already satisfy BCNF.
     866
     867Therefore, no further decomposition is required.
    634868}}}
    635869