| | 349 | |
| | 350 | == 3NF |
| | 351 | |
| | 352 | ==== PRODUCT |
| | 353 | {{{ |
| | 354 | Attributes : product_id, release_id, format, price, product_description, stock |
| | 355 | FDs : FD09 (product_id → release_id, format, price, product_description, stock) |
| | 356 | CKs / PK : {product_id} |
| | 357 | }}} |
| | 358 | {{{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**. |
| | 359 | |
| | 360 | ==== ARTIST |
| | 361 | {{{ |
| | 362 | Attributes : artist_id, artist_name, artist_description, artist_photo |
| | 363 | FDs : FD06 (artist_id → artist_name, artist_description, artist_photo) |
| | 364 | CKs / PK : {artist_id} |
| | 365 | }}} |
| | 366 | All non-key attributes depend directly on {{{artist_id}}}. There are no dependencies between non-key attributes. **No decomposition needed**. |
| | 367 | |
| | 368 | ==== RELEASE |
| | 369 | {{{ |
| | 370 | Attributes : release_id, title, record_label, genre, release_date, cover_photo, duration |
| | 371 | FDs : FD07 (release_id → title, record_label, genre, release_date, cover_photo, duration) |
| | 372 | CKs / PK : {release_id} |
| | 373 | }}} |
| | 374 | All non-key attributes depend directly on {{{release_id}}}. There is no non-key attribute that determines another non-key attribute. **No decomposition needed**. |
| | 375 | |
| | 376 | ==== SONG |
| | 377 | {{{ |
| | 378 | Attributes : song_id, song_name, song_duration |
| | 379 | FDs : FD08 (song_id → song_name, song_duration) |
| | 380 | CKs / PK : {song_id} |
| | 381 | }}} |
| | 382 | Only two non-key attributes exist, and both depend directly on {{{song_id}}}. No transitive dependency exists. **No decomposition needed**. |
| | 383 | |
| | 384 | ==== MODIFICATION |
| | 385 | {{{ |
| | 386 | Attributes : modification_id, admin_id, date_modified, type_of_modification, discount |
| | 387 | FDs : FD11 (modification_id → admin_id, date_modified, type_of_modification, discount) |
| | 388 | CKs / PK : {modification_id} |
| | 389 | }}} |
| | 390 | {{{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**. |
| | 391 | |
| | 392 | ==== ORDER |
| | 393 | {{{ |
| | 394 | Attributes : order_id, user_id, payment_method, purchase_date, points_earned, points_used, status |
| | 395 | FDs : FD10 (order_id → user_id, payment_method, purchase_date, points_earned, points_used, status) |
| | 396 | CKs / PK : {order_id} |
| | 397 | }}} |
| | 398 | {{{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**. |
| | 399 | |
| | 400 | ==== USER |
| | 401 | {{{ |
| | 402 | Attributes : user_id, email, username, password, date_created, shipping_address, telephone_number |
| | 403 | FDs : FD01 (user_id → email, username, password, date_created, shipping_address, telephone_number) |
| | 404 | FD02 (email → user_id) |
| | 405 | FD03 (username → user_id) |
| | 406 | CKs : {user_id}, {email}, {username} |
| | 407 | PK : user_id |
| | 408 | }}} |
| | 409 | {{{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**. |
| | 410 | |
| | 411 | ==== ORDER_PRODUCTS |
| | 412 | {{{ |
| | 413 | Attributes : order_id, product_id, price_at_purchase, quantity |
| | 414 | FDs : FD14 ((order_id, product_id) → price_at_purchase, quantity) |
| | 415 | CKs / PK : {order_id, product_id} |
| | 416 | }}} |
| | 417 | 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**. |
| | 418 | |
| | 419 | ==== WISHLIST_PRODUCTS |
| | 420 | {{{ |
| | 421 | Attributes : wishlist_id, product_id, added_at |
| | 422 | FDs : FD15 ((wishlist_id, product_id) → added_at) |
| | 423 | CKs / PK : {wishlist_id, product_id} |
| | 424 | }}} |
| | 425 | 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**. |
| | 426 | |
| | 427 | ==== RELEASE_ARTISTS |
| | 428 | {{{ |
| | 429 | Attributes : release_id, artist_id, release_ordinal, release_artist_type |
| | 430 | FDs : FD16 ((release_id, artist_id) → release_ordinal, release_artist_type) |
| | 431 | CKs / PK : {release_id, artist_id} |
| | 432 | }}} |
| | 433 | 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**. |
| | 434 | |
| | 435 | ==== SONG_ARTISTS |
| | 436 | {{{ |
| | 437 | Attributes : song_id, artist_id, song_ordinal |
| | 438 | FDs : FD17 ((song_id, artist_id) → song_ordinal) |
| | 439 | CKs / PK : {song_id, artist_id} |
| | 440 | }}} |
| | 441 | {{{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**. |
| | 442 | ==== ADMIN |
| | 443 | {{{ |
| | 444 | Attributes : user_id, admin_type, discount_percentage |
| | 445 | FDs : FD04 (user_id → admin_type, discount_percentage) |
| | 446 | CKs / PK : {user_id} |
| | 447 | }}} |
| | 448 | Both non-key attributes depend directly on **user_id**. Neither {{{admin_type}}} nor {{{discount_percentage}}} determines another attribute within the relation. **No decomposition needed**. |
| | 449 | ==== CONSUMER |
| | 450 | {{{ |
| | 451 | Attributes : user_id, points_collected |
| | 452 | FDs : FD05 (user_id → points_collected) |
| | 453 | CKs / PK : {user_id} |
| | 454 | }}} |
| | 455 | There is only one non-key attribute, and it depends directly on the candidate key. No transitive dependency is possible. **No decomposition needed**. |
| | 456 | ==== WISHLIST |
| | 457 | {{{ |
| | 458 | Attributes : user_id, wishlist_id |
| | 459 | FDs : FD12 (wishlist_id → user_id) |
| | 460 | FD13 (user_id → wishlist_id) |
| | 461 | CKs : {user_id}, {wishlist_id} |
| | 462 | PK : wishlist_id |
| | 463 | }}} |
| | 464 | {{{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**. |
| | 465 | |
| | 466 | == BCNF |
| | 467 | |
| | 468 | The primary keys are bolded. |
| | 469 | |
| | 470 | 1. PRODUCT(**product_id**, release_id, format, price, product_description, stock) → **satisfies BCNF** |
| | 471 | 2. ARTIST(**artist_id**, artist_name, artist_description, artist_photo) → satisfies BCNF |
| | 472 | 3. RELEASE(**release_id**, title, record_label, genre, release_date, cover_photo, duration) → **satisfies BCNF** |
| | 473 | 4. SONG(**song_id**, song_name, song_duration) → satisfies BCNF |
| | 474 | 5. MODIFICATION(**modification_id**, admin_id, date_modified, type_of_modification, discount) → **satisfies BCNF** |
| | 475 | 6. ORDER(**order_id**, user_id, payment_method, purchase_date, points_earned, points_used, status) → **satisfies BCNF** |
| | 476 | 7. USER(**user_id**, email, username, password, date_created, shipping_address, telephone_number) → **satisfies BCNF** |
| | 477 | 8. ORDER_PRODUCTS(**order_id**, **product_id**, price_at_purchase, quantity) → **satisfies BCNF** |
| | 478 | 9. WISHLIST_PRODUCTS(**wishlist_id**, **product_id**, added_at) → **satisfies BCNF** |
| | 479 | 10. RELEASE_ARTISTS(**release_id**, **artist_id**, release_ordinal, release_artist_type) → **satisfies BCNF** |
| | 480 | 11. SONG_ARTISTS(**song_id**, **artist_id**, song_ordinal) → **satisfies BCNF** |
| | 481 | 12. ADMIN(**user_id**, admin_type, discount_percentage) → **satisfies BCNF** |
| | 482 | 13. CONSUMER(**user_id**, points_collected) → **satisfies BCNF** |
| | 483 | 14. WISHLIST(**wishlist_id**, user_id) → **satisfies BCNF** |
| | 484 | 15. R15 = {**artist_id**, **album_id**, **song_id**, **product_id**, **order_id**, **modification_id**} → **satisfies BCNF** |