| 741 | | Примарен клуч на Universal_Relation_Shifter_Base_8: '''{saleId, poId, productId}''' |
| 742 | | |
| 743 | | '''Транзитивни зависности во U5:''' |
| 744 | | |
| 745 | | 1. '''FD1 транзитивно:''' {saleId, poId, productId} → userId (преку R2/saleId) → user_username, user_password, user_full_name, user_email, user_role, user_is_active |
| 746 | | * userId не е клуч на U5, а user_* зависат од userId |
| 747 | | * '''НАРУШУВА 3NF''' |
| 748 | | |
| 749 | | 2. '''FD4 транзитивно:''' {saleId, poId, productId} → customerId (преку R2/saleId) → customer_name, customer_email, customer_phone, customer_address |
| 750 | | * '''НАРУШУВА 3NF''' |
| 751 | | |
| 752 | | 3. '''FD7 транзитивно:''' {saleId, poId, productId} → categoryId (преку R1/productId) → category_name, category_description |
| 753 | | * '''НАРУШУВА 3NF''' |
| 754 | | |
| 755 | | 4. '''FD8 транзитивно:''' {saleId, poId, productId} → supplierId → supplier_name, supplier_contact_person, supplier_phone, supplier_email, supplier_address |
| 756 | | * '''НАРУШУВА 3NF''' |
| 757 | | |
| 758 | | 5. '''FD9 транзитивно:''' {saleId, poId, productId} → warehouseId → warehouse_name, warehouse_location, warehouse_capacity |
| 759 | | * '''НАРУШУВА 3NF''' |
| 760 | | |
| 761 | | 6. '''FD14:''' {warehouseId, productId} → stock_quantity_on_hand, stock_last_updated |
| 762 | | * warehouseId се добива транзитивно, а {warehouseId, productId} не е клуч на U5 |
| 763 | | * '''НАРУШУВА 3NF''' |
| 764 | | |
| 765 | | === Чекор 6.1: Декомпозиција по FD1 (userId → user_*) === |
| 766 | | |
| 767 | | {{{ |
| 768 | | R6(userId, user_username, user_password, user_full_name, user_email, user_role, user_is_active) |
| 769 | | PK: userId |
| 770 | | |
| 771 | | U6 = U5 - {user_username, user_password, user_full_name, user_email, user_role, user_is_active} |
| 772 | | |
| 773 | | U6(saleId, poId, productId, userId, customerId, customer_name, customer_email, |
| 774 | | customer_phone, customer_address, categoryId, category_name, category_description, |
| 775 | | supplierId, supplier_name, supplier_contact_person, supplier_phone, supplier_email, |
| 776 | | supplier_address, warehouseId, warehouse_name, warehouse_location, warehouse_capacity, |
| 777 | | stock_quantity_on_hand, stock_last_updated) |
| 778 | | }}} |
| 779 | | |
| 780 | | '''Проверка за lossless join:''' |
| 781 | | * R6 ∩ U6 = {userId} |
| 782 | | * userId → R6 (FD1) |
| 783 | | * Lossless ✓ |
| 784 | | |
| 785 | | === Чекор 6.2: Декомпозиција по FD4 (customerId → customer_*) === |
| 786 | | |
| 787 | | {{{ |
| 788 | | R7(customerId, customer_name, customer_email, customer_phone, customer_address) |
| 789 | | PK: customerId |
| 790 | | |
| 791 | | U7 = U6 - {customer_name, customer_email, customer_phone, customer_address} |
| 792 | | |
| 793 | | U7(saleId, poId, productId, userId, customerId, categoryId, category_name, |
| 794 | | category_description, supplierId, supplier_name, supplier_contact_person, |
| 795 | | supplier_phone, supplier_email, supplier_address, warehouseId, warehouse_name, |
| 796 | | warehouse_location, warehouse_capacity, stock_quantity_on_hand, stock_last_updated) |
| 797 | | }}} |
| 798 | | |
| 799 | | '''Проверка за lossless join:''' |
| 800 | | * R7 ∩ U7 = {customerId} |
| 801 | | * customerId → R7 (FD4) |
| 802 | | * Lossless ✓ |
| 803 | | |
| 804 | | === Чекор 6.3: Декомпозиција по FD7 (categoryId → category_*) === |
| 805 | | |
| 806 | | {{{ |
| 807 | | R8(categoryId, category_name, category_description) |
| 808 | | PK: categoryId |
| 809 | | |
| 810 | | U8 = U7 - {category_name, category_description} |
| 811 | | |
| 812 | | U8(saleId, poId, productId, userId, customerId, categoryId, supplierId, |
| 813 | | supplier_name, supplier_contact_person, supplier_phone, supplier_email, |
| 814 | | supplier_address, warehouseId, warehouse_name, warehouse_location, |
| 815 | | warehouse_capacity, stock_quantity_on_hand, stock_last_updated) |
| 816 | | }}} |
| 817 | | |
| 818 | | '''Проверка за lossless join:''' |
| 819 | | * R8 ∩ U8 = {categoryId} |
| 820 | | * categoryId → R8 (FD7) |
| 821 | | * Lossless ✓ |
| 822 | | |
| 823 | | === Чекор 6.4: Декомпозиција по FD8 (supplierId → supplier_*) === |
| 824 | | |
| 825 | | {{{ |
| 826 | | R9(supplierId, supplier_name, supplier_contact_person, supplier_phone, supplier_email, supplier_address) |
| 827 | | PK: supplierId |
| 828 | | |
| 829 | | U9 = U8 - {supplier_name, supplier_contact_person, supplier_phone, supplier_email, supplier_address} |
| 830 | | |
| 831 | | U9(saleId, poId, productId, userId, customerId, categoryId, supplierId, |
| 832 | | warehouseId, warehouse_name, warehouse_location, warehouse_capacity, |
| 833 | | stock_quantity_on_hand, stock_last_updated) |
| 834 | | }}} |
| 835 | | |
| 836 | | '''Проверка за lossless join:''' |
| 837 | | * R9 ∩ U9 = {supplierId} |
| 838 | | * supplierId → R9 (FD8) |
| 839 | | * Lossless ✓ |
| 840 | | |
| 841 | | === Чекор 6.5: Декомпозиција по FD9 (warehouseId → warehouse_*) === |
| 842 | | |
| 843 | | {{{ |
| 844 | | R10(warehouseId, warehouse_name, warehouse_location, warehouse_capacity) |
| 845 | | PK: warehouseId |
| 846 | | |
| 847 | | U10 = U9 - {warehouse_name, warehouse_location, warehouse_capacity} |
| 848 | | |
| 849 | | U10(saleId, poId, productId, userId, customerId, categoryId, supplierId, warehouseId, stock_quantity_on_hand, stock_last_updated) |
| 850 | | }}} |
| 851 | | |
| 852 | | '''Проверка за lossless join:''' |
| 853 | | * R10 ∩ U10 = {warehouseId} |
| 854 | | * warehouseId → R10 (FD9) |
| 855 | | * Lossless ✓ |
| 856 | | |
| 857 | | === Чекор 6.6: Декомпозиција по FD14 ({warehouseId, productId} → stock_*) === |
| 858 | | |
| 859 | | {{{ |
| 860 | | R11(warehouseId, productId, stock_quantity_on_hand, stock_last_updated) |
| 861 | | PK: {warehouseId, productId} |
| 862 | | |
| 863 | | U11 = U10 - {stock_quantity_on_hand, stock_last_updated} |
| 864 | | |
| 865 | | U11(saleId, poId, productId, userId, customerId, categoryId, supplierId, warehouseId) |
| 866 | | }}} |
| 867 | | |
| 868 | | '''Проверка за lossless join:''' |
| 869 | | * R11 ∩ U11 = {warehouseId, productId} |
| 870 | | * {warehouseId, productId} → R11 (FD14) |
| 871 | | * Lossless ✓ |
| 872 | | |
| 873 | | === Анализа на U11 === |
| 874 | | |
| 875 | | {{{ |
| 876 | | U11(saleId, poId, productId, userId, customerId, categoryId, supplierId, warehouseId) |
| 877 | | PK: {saleId, poId, productId} |
| 878 | | }}} |
| 879 | | |
| 880 | | Атрибутите userId, customerId, warehouseId се веќе дел од R2 (Sale). |
| 881 | | Атрибутите categoryId, supplierId се веќе дел од R1 (Product). |
| 882 | | |
| 883 | | U11 претставува врска меѓу продажби (saleId), нарачки (poId) и продукти (productId). |
| | 741 | Примарен клуч на Universal_Relation_Shifter_Base_8: '''∅''' |
| | 742 | |
| | 743 | '''Заклучок:''' После извлекување на сите парцијални зависности (FD2, FD3, FD4, FD10, FD12, FD14, FD16, FD17), универзалната релација е целосно декомпонирана. Примарниот клуч на Universal_Relation_Shifter_Base_8 е празно множество (∅), што значи дека таа релација повеќе не постои како валидна релација. |
| | 744 | Останатите функционални зависности (FD1, FD5-FD9, FD11, FD13, FD15) **нарушуваат 3NF** бидејќи нивните детерминанти (user_id, course_id, enrollment_id, итн.) не се примарни клучеви на |
| | 745 | Universal_Relation_Shifter_Base_8, туку се независни детерминанти кои треба да формираат посебни релации. |
| | 746 | |
| | 747 | === Чекор 6.1: Декомпозиција по FD1 (user_id → user_*) === |
| | 748 | |
| | 749 | {{{ |
| | 750 | User(user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points) |
| | 751 | PK: user_id |
| | 752 | |
| | 753 | Universal_Relation_Shifter_Base_9 = Universal_Relation_Shifter_Base_8 - {user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points} |
| | 754 | |
| | 755 | Universal_Relation_Shifter_Base_9( |
| | 756 | expert_id, |
| | 757 | course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price, |
| | 758 | course_version_id, version_number, version_creation_date, version_active, |
| | 759 | enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, |
| | 760 | payment_id, payment_amount, payment_date, payment_method, payment_status, |
| | 761 | review_id, review_rating, review_comment, review_date, |
| | 762 | course_content_id, content_position, |
| | 763 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 764 | tag_id, tag_type |
| | 765 | ) |
| | 766 | }}} |
| | 767 | |
| | 768 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id |
| | 769 | '''Проверка за dependency preservation:''' FD1 е зачувана во User |
| | 770 | |
| | 771 | === Чекор 6.2: Декомпозиција по FD5 (course_id → course_*) === |
| | 772 | |
| | 773 | {{{ |
| | 774 | Course(course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price) |
| | 775 | PK: course_id |
| | 776 | |
| | 777 | Universal_Relation_Shifter_Base_10 = Universal_Relation_Shifter_Base_9 - {course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price} |
| | 778 | |
| | 779 | Universal_Relation_Shifter_Base_10( |
| | 780 | expert_id, |
| | 781 | course_version_id, version_number, version_creation_date, version_active, |
| | 782 | enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, |
| | 783 | payment_id, payment_amount, payment_date, payment_method, payment_status, |
| | 784 | review_id, review_rating, review_comment, review_date, |
| | 785 | course_content_id, content_position, |
| | 786 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 787 | tag_id, tag_type |
| | 788 | ) |
| | 789 | }}} |
| | 790 | |
| | 791 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id → course_version_id |
| | 792 | '''Проверка за dependency preservation:''' FD5 е зачувана во Course |
| | 793 | |
| | 794 | === Чекор 6.3: Декомпозиција по FD6 (enrollment_id → enrollment_*) === |
| | 795 | |
| | 796 | {{{ |
| | 797 | Enrollment(enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id, payment_id, review_id) |
| | 798 | PK: enrollment_id |
| | 799 | |
| | 800 | Universal_Relation_Shifter_Base_11 = Universal_Relation_Shifter_Base_10 - {enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date} |
| | 801 | |
| | 802 | Universal_Relation_Shifter_Base_11( |
| | 803 | expert_id, |
| | 804 | course_version_id, version_number, version_creation_date, version_active, |
| | 805 | enrollment_id, |
| | 806 | payment_id, payment_amount, payment_date, payment_method, payment_status, |
| | 807 | review_id, review_rating, review_comment, review_date, |
| | 808 | course_content_id, content_position, |
| | 809 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 810 | tag_id, tag_type |
| | 811 | ) |
| | 812 | }}} |
| | 813 | |
| | 814 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id |
| | 815 | '''Проверка за dependency preservation:''' FD6 е зачувана во Enrollment |
| | 816 | |
| | 817 | === Чекор 6.4: Декомпозиција по FD7 (payment_id → payment_*) === |
| | 818 | |
| | 819 | {{{ |
| | 820 | Payment(payment_id, payment_amount, payment_date, payment_method, payment_status, enrollment_id) |
| | 821 | PK: payment_id |
| | 822 | |
| | 823 | Universal_Relation_Shifter_Base_12 = Universal_Relation_Shifter_Base_11 - {payment_amount, payment_date, payment_method, payment_status} |
| | 824 | |
| | 825 | Universal_Relation_Shifter_Base_12( |
| | 826 | expert_id, |
| | 827 | course_version_id, version_number, version_creation_date, version_active, |
| | 828 | enrollment_id, |
| | 829 | review_id, review_rating, review_comment, review_date, |
| | 830 | course_content_id, content_position, |
| | 831 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 832 | tag_id, tag_type |
| | 833 | ) |
| | 834 | }}} |
| | 835 | |
| | 836 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id |
| | 837 | '''Проверка за dependency preservation:''' FD7 е зачувана во Payment |
| | 838 | |
| | 839 | === Чекор 6.5: Декомпозиција по FD8 (review_id → review_*) === |
| | 840 | |
| | 841 | {{{ |
| | 842 | Review(review_id, review_rating, review_comment, review_date, enrollment_id) |
| | 843 | PK: review_id |
| | 844 | |
| | 845 | Universal_Relation_Shifter_Base_13 = Universal_Relation_Shifter_Base_12 - {review_rating, review_comment, review_date} |
| | 846 | |
| | 847 | Universal_Relation_Shifter_Base_13( |
| | 848 | expert_id, |
| | 849 | course_version_id, version_number, version_creation_date, version_active, |
| | 850 | enrollment_id, |
| | 851 | course_content_id, content_position, |
| | 852 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 853 | tag_id, tag_type |
| | 854 | ) |
| | 855 | }}} |
| | 856 | |
| | 857 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id |
| | 858 | '''Проверка за dependency preservation:''' FD8 е зачувана во Review |
| | 859 | |
| | 860 | === Чекор 6.6: Декомпозиција по FD9 (tag_id → tag_*) === |
| | 861 | |
| | 862 | {{{ |
| | 863 | Tag(tag_id, tag_type) |
| | 864 | PK: tag_id |
| | 865 | |
| | 866 | Universal_Relation_Shifter_Base_14 = Universal_Relation_Shifter_Base_13 - {tag_type} |
| | 867 | |
| | 868 | Universal_Relation_Shifter_Base_14( |
| | 869 | expert_id, |
| | 870 | course_version_id, version_number, version_creation_date, version_active, |
| | 871 | enrollment_id, |
| | 872 | course_content_id, content_position, |
| | 873 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 874 | tag_id |
| | 875 | ) |
| | 876 | }}} |
| | 877 | |
| | 878 | '''Проверка за lossless join:''' Може да се реконструира преку tag_id |
| | 879 | '''Проверка за dependency preservation:''' FD9 е зачувана во Tag |
| | 880 | |
| | 881 | === Чекор 6.7: Декомпозиција по FD11 (course_version_id → course_version_*) === |
| | 882 | |
| | 883 | {{{ |
| | 884 | Course_Version(course_version_id, version_number, version_creation_date, version_active, course_id) |
| | 885 | PK: course_version_id |
| | 886 | |
| | 887 | Universal_Relation_Shifter_Base_15 = Universal_Relation_Shifter_Base_14 - {course_version_id, version_number, version_creation_date, version_active} |
| | 888 | |
| | 889 | Universal_Relation_Shifter_Base_15( |
| | 890 | expert_id, |
| | 891 | enrollment_id, |
| | 892 | course_content_id, content_position, |
| | 893 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 894 | tag_id |
| | 895 | ) |
| | 896 | }}} |
| | 897 | |
| | 898 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id |
| | 899 | '''Проверка за dependency preservation:''' FD11 е зачувана во Course_Version |
| | 900 | |
| | 901 | === Чекор 6.8: Декомпозиција по FD13 (course_content_id → course_content_*) === |
| | 902 | |
| | 903 | {{{ |
| | 904 | Course_Content(course_content_id, content_position, course_version_id) |
| | 905 | PK: course_content_id |
| | 906 | |
| | 907 | Universal_Relation_Shifter_Base_16 = Universal_Relation_Shifter_Base_15 - {course_content_id, content_position} |
| | 908 | |
| | 909 | Universal_Relation_Shifter_Base_16( |
| | 910 | expert_id, |
| | 911 | enrollment_id, |
| | 912 | course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, |
| | 913 | tag_id |
| | 914 | ) |
| | 915 | }}} |
| | 916 | |
| | 917 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id → course_version_id |
| | 918 | '''Проверка за dependency preservation:''' FD13 е зачувана во Course_Content |
| | 919 | |
| | 920 | === Чекор 6.9: Декомпозиција по FD15 (course_lecture_id → course_lecture_*) === |
| | 921 | |
| | 922 | {{{ |
| | 923 | Course_Lecture(course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, course_content_id) |
| | 924 | PK: course_lecture_id |
| | 925 | |
| | 926 | Universal_Relation_Shifter_Base_17 = Universal_Relation_Shifter_Base_16 - {course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type} |
| | 927 | |
| | 928 | Universal_Relation_Shifter_Base_17( |
| | 929 | expert_id, |
| | 930 | enrollment_id, |
| | 931 | tag_id |
| | 932 | ) |
| | 933 | }}} |
| | 934 | |
| | 935 | '''Проверка за lossless join:''' Може да се реконструира преку enrollment_id → course_version_id → course_content_id |
| | 936 | '''Проверка за dependency preservation:''' FD15 е зачувана во Course_Lecture |
| | 937 | |
| | 938 | === Анализа на Universal_Relation_Shifter_Base_17 === |
| | 939 | |
| | 940 | {{{ |
| | 941 | Universal_Relation_Shifter_Base_17( |
| | 942 | expert_id, |
| | 943 | enrollment_id, |
| | 944 | tag_id |
| | 945 | ) |
| | 946 | }}} |
| | 947 | |
| | 948 | |
| | 949 | Universal_Relation_Shifter_Base_17 претставува колекција од foreign keys кои треба да се организираат во посебни many-to-many junction tables. |