Changes between Version 12 and Version 13 of normalization


Ignore:
Timestamp:
01/30/26 10:20:59 (6 hours ago)
Author:
231175
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • normalization

    v12 v13  
    739739==== Universal_Relation_Shifter_Base_8 - Проверка за транзитивни зависности ====
    740740
    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, итн.) не се примарни клучеви на
     745Universal_Relation_Shifter_Base_8, туку се независни детерминанти кои треба да формираат посебни релации.
     746
     747=== Чекор 6.1: Декомпозиција по FD1 (user_id → user_*) ===
     748
     749{{{
     750User(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
     753Universal_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
     755Universal_Relation_Shifter_Base_9(
     756expert_id,
     757course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
     758course_version_id, version_number, version_creation_date, version_active,
     759enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
     760payment_id, payment_amount, payment_date, payment_method, payment_status,
     761review_id, review_rating, review_comment, review_date,
     762course_content_id, content_position,
     763course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     764tag_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{{{
     774Course(course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price)
     775   PK: course_id
     776
     777Universal_Relation_Shifter_Base_10 = Universal_Relation_Shifter_Base_9 - {course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price}
     778
     779Universal_Relation_Shifter_Base_10(
     780expert_id,
     781course_version_id, version_number, version_creation_date, version_active,
     782enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
     783payment_id, payment_amount, payment_date, payment_method, payment_status,
     784review_id, review_rating, review_comment, review_date,
     785course_content_id, content_position,
     786course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     787tag_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{{{
     797Enrollment(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
     800Universal_Relation_Shifter_Base_11 = Universal_Relation_Shifter_Base_10 - {enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date}
     801
     802Universal_Relation_Shifter_Base_11(
     803expert_id,
     804course_version_id, version_number, version_creation_date, version_active,
     805enrollment_id,
     806payment_id, payment_amount, payment_date, payment_method, payment_status,
     807review_id, review_rating, review_comment, review_date,
     808course_content_id, content_position,
     809course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     810tag_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{{{
     820Payment(payment_id, payment_amount, payment_date, payment_method, payment_status, enrollment_id)
     821   PK: payment_id
     822
     823Universal_Relation_Shifter_Base_12 = Universal_Relation_Shifter_Base_11 - {payment_amount, payment_date, payment_method, payment_status}
     824
     825Universal_Relation_Shifter_Base_12(
     826expert_id,
     827course_version_id, version_number, version_creation_date, version_active,
     828enrollment_id,
     829review_id, review_rating, review_comment, review_date,
     830course_content_id, content_position,
     831course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     832tag_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{{{
     842Review(review_id, review_rating, review_comment, review_date, enrollment_id)
     843   PK: review_id
     844
     845Universal_Relation_Shifter_Base_13 = Universal_Relation_Shifter_Base_12 - {review_rating, review_comment, review_date}
     846
     847Universal_Relation_Shifter_Base_13(
     848expert_id,
     849course_version_id, version_number, version_creation_date, version_active,
     850enrollment_id,
     851course_content_id, content_position,
     852course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     853tag_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{{{
     863Tag(tag_id, tag_type)
     864   PK: tag_id
     865
     866Universal_Relation_Shifter_Base_14 = Universal_Relation_Shifter_Base_13 - {tag_type}
     867
     868Universal_Relation_Shifter_Base_14(
     869expert_id,
     870course_version_id, version_number, version_creation_date, version_active,
     871enrollment_id,
     872course_content_id, content_position,
     873course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     874tag_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{{{
     884Course_Version(course_version_id, version_number, version_creation_date, version_active, course_id)
     885   PK: course_version_id
     886
     887Universal_Relation_Shifter_Base_15 = Universal_Relation_Shifter_Base_14 - {course_version_id, version_number, version_creation_date, version_active}
     888
     889Universal_Relation_Shifter_Base_15(
     890expert_id,
     891enrollment_id,
     892course_content_id, content_position,
     893course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     894tag_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{{{
     904Course_Content(course_content_id, content_position, course_version_id)
     905   PK: course_content_id
     906
     907Universal_Relation_Shifter_Base_16 = Universal_Relation_Shifter_Base_15 - {course_content_id, content_position}
     908
     909Universal_Relation_Shifter_Base_16(
     910expert_id,
     911enrollment_id,
     912course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     913tag_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{{{
     923Course_Lecture(course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, course_content_id)
     924   PK: course_lecture_id
     925
     926Universal_Relation_Shifter_Base_17 = Universal_Relation_Shifter_Base_16 - {course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type}
     927
     928Universal_Relation_Shifter_Base_17(
     929expert_id,
     930enrollment_id,
     931tag_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{{{
     941Universal_Relation_Shifter_Base_17(
     942expert_id,
     943enrollment_id,
     944tag_id
     945)
     946}}}
     947
     948
     949Universal_Relation_Shifter_Base_17 претставува колекција од foreign keys кои треба да се организираат во посебни many-to-many junction tables.
    884950
    885951'''Прашање:''' Дали оваа релација има семантичка смисла?
    886 
    887 Во реалноста:
    888  * Една продажба (saleId) е независна од една нарачка (poId)
    889  * Нивната врска е само преку productId и warehouseId
    890 
    891 '''U11 може да се декомпонира понатаму''', бидејќи атрибутите userId, customerId, warehouseId зависат само од saleId (FD10), а supplierId зависи само од poId или productId.
    892 
    893 Но бидејќи овие атрибути се веќе издвоени во R2 и R1, U11 станува редундантна и може да се отстрани бидејќи информацијата е веќе зачувана во другите релации.
     952'''Одговор:''' НЕ! Universal_Relation_Shifter_Base_17 е само технички резултат од декомпозициите и не претставува ниеден реален бизнис концепт.
     953
     954'''Заклучок од 3NF:'''
     955Сите функционални зависности (FD1-FD27) се организирани во релации кои се во 3NF. Universal_Relation_Shifter_Base_17 повеќе не постои како валидна релација.
     956
     957'''Останати врски (many-to-many):'''
     958Foreign keys во Universal_Relation_Shifter_Base_17 укажуваат на many-to-many релации кои НЕ се дефинирани преку функционални зависности, туку преку бизнис логика:
     959
     960* '''User_Tag'''(user_id, tag_id) - корисник има интереси
     961* '''Course_Tag'''(course_id, tag_id) - курс има тагови 
     962* '''Expert_Course'''(expert_id, course_id) - експерт предава курсеви
    894963
    895964=== Состојба после 3NF декомпозиција ===