Changes between Initial Version and Version 1 of Normalization


Ignore:
Timestamp:
09/16/26 14:17:27 (12 days ago)
Author:
233149
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v1 v1  
     1== Нормализација
     2
     3== Денормализирана форма на базата
     4
     5Постапката започнува од една единствена денормализирана релација '''R''' која ги
     6содржи сите атрибути од ЕР моделот, како целата база да е сместена во една табела.
     7
     8Бидејќи во моделот повеќе ентитети имаат атрибут со исто име (id, name, type,
     9created_at), атрибутите се преименувани така што во R нема две исти имиња:
     10
     11 * id → user_id, high_school_id, contact_id, major_id, semester_id, subject_id, enrolled_id, sem_subject_id, passed_id, document_id, token_id, payment_id
     12 * name → user_name, major_name, subject_name
     13 * type → hs_type, semester_type, document_type
     14 * created_at → user_created_at, enrolled_created_at
     15 * number → phone_number, index → index_no, body → document_body, cost → document_cost, token → token_value, quota → quota (на корисник) и enrolled_quota (на запишан семестар)
     16 * улогите на professor се разликуваат: professor_id (професор на конкретен запишан предмет) и teaching_prof_id (професор во распоредот по семестар)
     17 * dependency_id → prerequisite_id (предметот кој е предуслов)
     18
     19'''R''' = { user_id, user_name, embg, surname, index_no, bday, email, password,
     20role, quota, enrollment_year, user_created_at, high_school_id, gpa, hs_type,
     21contact_id, city, municipality, address, phone_number, microsoft_email, major_id,
     22major_name, semester_id, year, semester_type, subject_id, subject_name,
     23subject_code, awarded_credits, dependency_credit, enrolled_id, enrolled_quota,
     24note, student_comment, enrolled_created_at, last_change, completed,
     25sem_subject_id, professor_id, signature, passed_id, grade, date_passed,
     26document_id, document_type, document_body, document_cost, token_id, token_value,
     27expires_at, is_valid, payment_id, amount, mandatory_semester, prerequisite_id,
     28teaching_prof_id }
     29
     30Вкупно '''|R| = 57''' атрибути.
     31
     32== Функционални зависности
     33
     34Даден е каноничкиот покривач на множеството функционални зависности кои важат во R:
     35
     36 * '''FD1''': user_id → user_name, embg, surname, index_no, bday, email, password, role, quota, enrollment_year, user_created_at
     37 * '''FD2''': email → user_id
     38 * '''FD3''': user_id → high_school_id
     39 * '''FD4''': high_school_id → user_id, gpa, hs_type
     40 * '''FD5''': user_id → contact_id
     41 * '''FD6''': contact_id → user_id, city, municipality, address, phone_number, microsoft_email
     42 * '''FD7''': major_id → major_name
     43 * '''FD8''': semester_id → year, semester_type
     44 * '''FD9''': (year, semester_type) → semester_id
     45 * '''FD10''': subject_id → subject_name, subject_code, awarded_credits, dependency_credit
     46 * '''FD11''': subject_name → subject_id
     47 * '''FD12''': subject_code → subject_id
     48 * '''FD13''': enrolled_id → user_id, enrolled_quota, major_id, note, student_comment, enrolled_created_at, last_change, completed, semester_id
     49 * '''FD14''': (user_id, semester_id) → enrolled_id
     50 * '''FD15''': sem_subject_id → enrolled_id, subject_id, professor_id, signature
     51 * '''FD16''': (enrolled_id, subject_id) → sem_subject_id
     52 * '''FD17''': passed_id → sem_subject_id, grade, date_passed
     53 * '''FD18''': sem_subject_id → passed_id, grade, date_passed
     54 * '''FD19''': document_id → document_type, document_body, document_cost
     55 * '''FD20''': token_id → user_id, token_value, expires_at, is_valid
     56 * '''FD21''': payment_id → user_id, enrolled_id, amount
     57 * '''FD22''': (major_id, subject_id) → mandatory_semester
     58
     59Следните комбинации не определуваат ниту еден атрибут, односно претставуваат чисти
     60врски (сите атрибути се дел од клучот):
     61
     62 * '''FD23''': (user_id, document_id) → ∅
     63 * '''FD24''': (subject_id, prerequisite_id) → ∅
     64 * '''FD25''': (teaching_prof_id, semester_id, subject_id) → ∅
     65
     66Зависностите FD2, FD9, FD11, FD12, FD14, FD16 и FD17 произлегуваат од UNIQUE
     67ограничувањата, а FD4 и FD6 од тоа што врските се 1:1.
     68
     69== Кандидат клучеви и примарен клуч
     70
     71'''Атрибути кои се појавуваат само лево''' (мора да бидат дел од секој кандидат клуч):
     72
     73 document_id, token_id, payment_id, prerequisite_id, teaching_prof_id
     74
     75'''Атрибути кои се појавуваат само десно''' (не можат да бидат дел од кандидат клуч), 38 атрибути:
     76
     77 address, amount, awarded_credits, bday, city, completed, date_passed,
     78 dependency_credit, document_body, document_cost, document_type, embg,
     79 enrolled_created_at, enrolled_quota, enrollment_year, expires_at, gpa, grade,
     80 hs_type, index_no, is_valid, last_change, major_name, mandatory_semester,
     81 microsoft_email, municipality, note, password, phone_number, professor_id,
     82 quota, role, signature, student_comment, surname, token_value, user_created_at,
     83 user_name
     84
     85'''Атрибути кои се појавуваат и лево и десно''' (кандидати за дополнување на клучот), 14 атрибути:
     86
     87 contact_id, email, enrolled_id, high_school_id, major_id, passed_id,
     88 sem_subject_id, semester_id, semester_type, subject_code, subject_id,
     89 subject_name, user_id, year
     90
     91=== Покривач на јадрото
     92
     93Нека '''K''' = { document_id, token_id, payment_id, prerequisite_id, teaching_prof_id }.
     94
     95'''K+''' содржи 45 од вкупно 57 атрибути. Не се добиваат:
     96
     97 awarded_credits, date_passed, dependency_credit, grade, mandatory_semester,
     98 passed_id, professor_id, sem_subject_id, signature, subject_code, subject_id,
     99 subject_name
     100
     101Значи K сам по себе '''не е суперклуч'''. Причината е што ниту еден од атрибутите
     102во K не води до предметот: до sem_subject_id се стигнува само преку
     103(enrolled_id, subject_id) со FD16 или преку passed_id со FD17, а subject_id не се
     104добива од ниту една зависност чија лева страна е во K+.
     105
     106=== Кандидат клучеви
     107
     108Со додавање на еден атрибут од двостраните на K се добиваат следните минимални
     109суперклучеви, односно кандидат клучеви:
     110
     111 * '''CK1''' = K ∪ { subject_id }
     112 * '''CK2''' = K ∪ { sem_subject_id }
     113 * '''CK3''' = K ∪ { passed_id }
     114 * '''CK4''' = K ∪ { subject_code }
     115 * '''CK5''' = K ∪ { subject_name }
     116
     117CK4 и CK5 постојат затоа што subject_code и subject_name се UNIQUE, па се
     118алтернативни идентификатори на предметот. CK2 и CK3 постојат затоа што
     119sem_subject_id и passed_id се во однос 1:1 и секој од нив води до subject_id.
     120
     121'''Избран примарен клуч:'''
     122
     123 PK = { document_id, token_id, payment_id, prerequisite_id, teaching_prof_id, subject_id }
     124
     125Избран е CK1 бидејќи subject_id е природниот идентификатор на предметот, додека
     126sem_subject_id и passed_id се идентификатори на врски кои постојат само ако
     127студентот го запишал, односно положил предметот.
     128
     129=== Проверка во која нормална форма е R
     130
     131Релацијата R ја задоволува '''1НФ''': сите атрибути се атомични, нема
     132повеќевредносни атрибути ниту повторувачки групи, и секоја редица е определена со PK.
     133
     134R '''не ја задоволува 2НФ''', бидејќи постојат парцијални зависности - атрибути кои
     135зависат од дел од примарниот клуч, а не од целиот. На пример document_id →
     136document_type, каде document_id е само еден дел од PK.
     137
     138== 1НФ декомпозиција
     139
     140Не е потребна декомпозиција. R е веќе во 1НФ: секој атрибут има атомична вредност
     141од единствен домен, нема повторувачки групи и секоја редица е уникатно определена
     142со примарниот клуч.
     143
     144== 2НФ декомпозиција
     145
     146'''Анализирана релација:''' R, PK = { document_id, token_id, payment_id, prerequisite_id, teaching_prof_id, subject_id }
     147
     148'''Парцијални зависности''' (лева страна е вистински подмножество на PK):
     149
     150 * FD19: document_id → document_type, document_body, document_cost
     151 * FD20: token_id → token_value, expires_at, is_valid
     152 * FD21: payment_id → amount
     153 * FD10: subject_id → subject_name, subject_code, awarded_credits, dependency_credit
     154
     155Секоја од нив се издвојува во посебна релација. Атрибутите кои се клучеви или се
     156потребни за поврзување остануваат и во преостанатата релација.
     157
     158=== Декомпозиција по FD19
     159
     160 '''Documents'''(''__document_id__'', document_type, document_body, document_cost)
     161
     162 R1 = R − { document_type, document_body, document_cost }
     163
     164 * Клуч: document_id
     165 * ''Lossless join'': спојувањето по document_id ја реконструира R, бидејќи document_id е клуч на Documents.
     166 * ''Dependency preservation'': FD19 е сочувана во Documents.
     167
     168=== Декомпозиција по FD20
     169
     170 '''Token'''(''__token_id__'', user_id, token_value, expires_at, is_valid)
     171
     172 R2 = R1 − { token_value, expires_at, is_valid }
     173
     174 * Клуч: token_id
     175 * ''Lossless join'': спојување по token_id; token_id е клуч на Token.
     176 * ''Dependency preservation'': FD20 е сочувана во Token.
     177
     178=== Декомпозиција по FD21
     179
     180 '''Payment'''(''__payment_id__'', enrolled_id, amount)
     181
     182 R3 = R2 − { amount }
     183
     184 * Клуч: payment_id
     185 * ''Lossless join'': спојување по payment_id.
     186 * ''Dependency preservation'': FD21 е сочувана во Payment.
     187 * '''Забелешка:''' атрибутот user_id намерно '''не''' е дел од Payment. Види ја дискусијата за БКНФ подолу.
     188
     189=== Декомпозиција по FD10
     190
     191 '''Subjects'''(''__subject_id__'', subject_name, subject_code, awarded_credits, dependency_credit)
     192
     193 R4 = R3 − { subject_name, subject_code, awarded_credits, dependency_credit }
     194
     195 * Клучеви: subject_id (примарен), subject_name, subject_code (алтернативни, поради FD11 и FD12)
     196 * ''Lossless join'': спојување по subject_id.
     197 * ''Dependency preservation'': FD10, FD11 и FD12 се сочувани во Subjects.
     198
     199'''Резултат по 2НФ:'''
     200
     201 R4 = { user_id, user_name, embg, surname, index_no, bday, email, password, role,
     202 quota, enrollment_year, user_created_at, high_school_id, gpa, hs_type,
     203 contact_id, city, municipality, address, phone_number, microsoft_email,
     204 major_id, major_name, semester_id, year, semester_type, subject_id,
     205 enrolled_id, enrolled_quota, note, student_comment, enrolled_created_at,
     206 last_change, completed, sem_subject_id, professor_id, signature, passed_id,
     207 grade, date_passed, document_id, token_id, payment_id, mandatory_semester,
     208 prerequisite_id, teaching_prof_id }
     209
     210== 3НФ декомпозиција
     211
     212R4 не ја задоволува 3НФ поради транзитивни зависности: token_id → user_id →
     213user_name, payment_id → enrolled_id → major_id → major_name, и слично.
     214
     215=== Декомпозиција по FD1
     216
     217 '''Users'''(''__user_id__'', user_name, embg, surname, index_no, bday, email, password, role, quota, enrollment_year, user_created_at)
     218
     219 R5 = R4 − { user_name, embg, surname, index_no, bday, email, password, role, quota, enrollment_year, user_created_at }
     220
     221 * Клучеви: user_id (примарен), email (алтернативен, поради FD2)
     222 * Транзитивна зависност: token_id → user_id → останатите атрибути на корисникот
     223 * ''Lossless join'': спојување по user_id.
     224 * ''Dependency preservation'': FD1 и FD2 се сочувани во Users.
     225
     226=== Декомпозиција по FD4
     227
     228 '''HighSchool'''(''__high_school_id__'', user_id, gpa, hs_type)
     229
     230 R6 = R5 − { gpa, hs_type }
     231
     232 * Клучеви: high_school_id (примарен), user_id (алтернативен, поради FD3 - врската е 1:1)
     233 * ''Lossless join'': спојување по high_school_id.
     234 * ''Dependency preservation'': FD3 и FD4 се сочувани во HighSchool.
     235
     236=== Декомпозиција по FD6
     237
     238 '''Contact'''(''__contact_id__'', user_id, city, municipality, address, phone_number, microsoft_email)
     239
     240 R7 = R6 − { city, municipality, address, phone_number, microsoft_email }
     241
     242 * Клучеви: contact_id (примарен), user_id (алтернативен, поради FD5)
     243 * ''Lossless join'': спојување по contact_id.
     244 * ''Dependency preservation'': FD5 и FD6 се сочувани во Contact.
     245
     246=== Декомпозиција по FD13
     247
     248 '''EnrolledSemesters'''(''__enrolled_id__'', user_id, enrolled_quota, major_id, note, student_comment, enrolled_created_at, last_change, completed, semester_id)
     249
     250 R8 = R7 − { enrolled_quota, note, student_comment, enrolled_created_at, last_change, completed }
     251
     252 * Клучеви: enrolled_id (примарен), (user_id, semester_id) (алтернативен, поради FD14)
     253 * Транзитивна зависност: payment_id → enrolled_id → атрибутите на запишувањето
     254 * ''Lossless join'': спојување по enrolled_id.
     255 * ''Dependency preservation'': FD13 и FD14 се сочувани во EnrolledSemesters.
     256
     257=== Декомпозиција по FD7
     258
     259 '''Major'''(''__major_id__'', major_name)
     260
     261 R9 = R8 − { major_name }
     262
     263 * Клуч: major_id
     264 * Транзитивна зависност: enrolled_id → major_id → major_name
     265 * ''Lossless join'': спојување по major_id.
     266 * ''Dependency preservation'': FD7 е сочувана во Major.
     267
     268=== Декомпозиција по FD8
     269
     270 '''ActiveSemesters'''(''__semester_id__'', year, semester_type)
     271
     272 R10 = R9 − { year, semester_type }
     273
     274 * Клучеви: semester_id (примарен), (year, semester_type) (алтернативен, поради FD9)
     275 * Транзитивна зависност: enrolled_id → semester_id → year, semester_type
     276 * ''Lossless join'': спојување по semester_id.
     277 * ''Dependency preservation'': FD8 и FD9 се сочувани во ActiveSemesters.
     278
     279=== Декомпозиција по FD15
     280
     281 '''SemestersSubjects'''(''__sem_subject_id__'', enrolled_id, subject_id, professor_id, signature)
     282
     283 R11 = R10 − { professor_id, signature }
     284
     285 * Клучеви: sem_subject_id (примарен), (enrolled_id, subject_id) (алтернативен, поради FD16)
     286 * ''Lossless join'': спојување по sem_subject_id.
     287 * ''Dependency preservation'': FD15 и FD16 се сочувани во SemestersSubjects.
     288
     289=== Декомпозиција по FD17
     290
     291 '''PassedSubjects'''(''__passed_id__'', sem_subject_id, grade, date_passed)
     292
     293 R12 = R11 − { grade, date_passed }
     294
     295 * Клучеви: passed_id (примарен), sem_subject_id (алтернативен, поради FD18 - врската е 1:1)
     296 * ''Lossless join'': спојување по passed_id.
     297 * ''Dependency preservation'': FD17 и FD18 се сочувани во PassedSubjects.
     298
     299=== Декомпозиција по FD22
     300
     301 '''MajorSubjects'''(''__major_id__'', ''__subject_id__'', mandatory_semester)
     302
     303 R13 = R12 − { mandatory_semester }
     304
     305 * Клуч: (major_id, subject_id)
     306 * Зависноста FD22 има сложена лева страна која не е клуч на R12, што ја нарушува 3НФ.
     307 * ''Lossless join'': спојување по (major_id, subject_id).
     308 * ''Dependency preservation'': FD22 е сочувана во MajorSubjects.
     309
     310'''Резултат по 3НФ:'''
     311
     312 R13 = { user_id, high_school_id, contact_id, major_id, semester_id, subject_id,
     313 enrolled_id, sem_subject_id, passed_id, document_id, token_id, payment_id,
     314 prerequisite_id, teaching_prof_id }
     315
     316Во R13 остануваат само идентификатори. Сите зависности со неклучна десна страна
     317се веќе издвоени.
     318
     319== БКНФ
     320
     321Секоја од добиените релации се проверува дали секоја лева страна на функционална
     322зависност во неа е суперклуч на таа релација.
     323
     324 * Users - детерминанти user_id и email, обата се кандидат клучеви → БКНФ
     325 * HighSchool - детерминанти high_school_id и user_id, обата се кандидат клучеви → БКНФ
     326 * Contact - детерминанти contact_id и user_id, обата се кандидат клучеви → БКНФ
     327 * Major - детерминанта major_id → БКНФ
     328 * ActiveSemesters - детерминанти semester_id и (year, semester_type) → БКНФ
     329 * Subjects - детерминанти subject_id, subject_name, subject_code, сите кандидат клучеви → БКНФ
     330 * EnrolledSemesters - детерминанти enrolled_id и (user_id, semester_id) → БКНФ
     331 * SemestersSubjects - детерминанти sem_subject_id и (enrolled_id, subject_id) → БКНФ
     332 * PassedSubjects - детерминанти passed_id и sem_subject_id → БКНФ
     333 * Documents - детерминанта document_id → БКНФ
     334 * Token - детерминанта token_id → БКНФ
     335 * Payment - детерминанта payment_id → БКНФ
     336 * MajorSubjects - детерминанта (major_id, subject_id) → БКНФ
     337
     338=== Пронајдено нарушување на БКНФ
     339
     340Ако релацијата Payment се дефинира како во Фаза 2:
     341
     342 Payment(''__payment_id__'', user_id, enrolled_id, amount)
     343
     344тогаш во неа важи и зависноста '''enrolled_id → user_id''' (изведена од FD13),
     345а enrolled_id '''не е''' клуч на Payment. Ова е нарушување на БКНФ и значи дека
     346атрибутот user_id во Payment е редундантен: студентот е веќе определен преку
     347запишувањето кое се плаќа.
     348
     349Практичната последица е можност за противречни податоци - ред во Payment може да
     350тврди дека плаќањето е на еден студент, додека запишувањето на кое се однесува
     351припаѓа на друг студент. Базата тоа не го спречува.
     352
     353'''Декомпозиција по enrolled_id → user_id:'''
     354
     355 Payment(''__payment_id__'', enrolled_id, amount)
     356
     357 user_id се добива со спојување преку EnrolledSemesters.
     358
     359 * ''Lossless join'': enrolled_id е надворешен клуч кон EnrolledSemesters, каде е клуч, па спојувањето е без загуба.
     360 * ''Dependency preservation'': FD21 останува сочувана, бидејќи payment_id → enrolled_id, amount е во Payment, а payment_id → user_id се изведува транзитивно преку FD13.
     361
     362По оваа измена '''сите релации се во БКНФ'''.
     363
     364== 4НФ
     365
     366Преостанатата релација R13 содржи само идентификатори и во неа постојат
     367повеќевредносни зависности кои се меѓусебно независни. На пример, документите кои
     368ги побарал еден корисник се независни од предусловите меѓу предметите и од
     369распоредот на професорите.
     370
     371'''Декомпозиција по 4НФ:'''
     372
     373 * '''UserDocuments'''(''__user_id__'', ''__document_id__'') - од FD23
     374 * '''DependencySubject'''(''__subject_id__'', ''__prerequisite_id__'') - од FD24
     375 * '''ProfessourSubjects'''(''__teaching_prof_id__'', ''__semester_id__'', ''__subject_id__'') - од FD25
     376
     377Останатите идентификатори од R13 (high_school_id, contact_id, major_id,
     378enrolled_id, sem_subject_id, passed_id, token_id, payment_id) веќе се примарни
     379клучеви во претходно издвоените релации, па не формираат нова релација.
     380
     381 * ''Lossless join'': спојување по заедничките атрибути ја враќа R13.
     382 * ''Dependency preservation'': трите нови релации не носат функционални зависности, туку само врски.
     383
     384== Финален резултат и дискусија
     385
     386=== Нормализиран релациски модел
     387
     388 1. '''Users'''(''__user_id__'', user_name, embg, surname, index_no, bday, email, password, role, quota, enrollment_year, user_created_at)
     389 2. '''HighSchool'''(''__high_school_id__'', user_id, gpa, hs_type)
     390 3. '''Contact'''(''__contact_id__'', user_id, city, municipality, address, phone_number, microsoft_email)
     391 4. '''Major'''(''__major_id__'', major_name)
     392 5. '''ActiveSemesters'''(''__semester_id__'', year, semester_type)
     393 6. '''Subjects'''(''__subject_id__'', subject_name, subject_code, awarded_credits, dependency_credit)
     394 7. '''EnrolledSemesters'''(''__enrolled_id__'', user_id, enrolled_quota, major_id, note, student_comment, enrolled_created_at, last_change, completed, semester_id)
     395 8. '''SemestersSubjects'''(''__sem_subject_id__'', enrolled_id, subject_id, professor_id, signature)
     396 9. '''PassedSubjects'''(''__passed_id__'', sem_subject_id, grade, date_passed)
     397 10. '''Documents'''(''__document_id__'', document_type, document_body, document_cost)
     398 11. '''UserDocuments'''(''__user_id__'', ''__document_id__'')
     399 12. '''Token'''(''__token_id__'', user_id, token_value, expires_at, is_valid)
     400 13. '''Payment'''(''__payment_id__'', enrolled_id, amount)
     401 14. '''MajorSubjects'''(''__major_id__'', ''__subject_id__'', mandatory_semester)
     402 15. '''DependencySubject'''(''__subject_id__'', ''__prerequisite_id__'')
     403 16. '''ProfessourSubjects'''(''__teaching_prof_id__'', ''__semester_id__'', ''__subject_id__'')
     404
     405Сите 16 релации се во БКНФ, декомпозицијата ги сочувува сите функционални
     406зависности и е без загуба при спојување.
     407
     408=== Дискусија
     409
     410Постапката на нормализација, спроведена независно од дизајнот на Фаза 2, даде
     411'''практично ист резултат''' - истите 16 релации, со исти клучеви. Тоа значи дека
     412ЕР моделот од Фаза 1 и релацискиот дизајн од Фаза 2 биле соодветно направени.
     413
     414Постои '''една разлика''', и таа е вистинска грешка во дизајнот од Фаза 2:
     415
     416 * '''Фаза 2''': Payment(''__id__'', user_id, enrollment_id, amount)
     417 * '''По нормализација''': Payment(''__id__'', enrollment_id, amount)
     418
     419Атрибутот user_id е редундантен, бидејќи enrollment_id → user_id. Покрај
     420редундантноста, ваквиот дизајн дозволува аномалија при ажурирање: плаќање може да
     421биде запишано на еден студент, а да се однесува на запишување на друг студент,
     422што базата не го спречува со ниту едно ограничување.
     423
     424За наредните фази се користи '''нормализираниот модел''', односно табелата payment
     425повеќе не содржи user_id. Скриптите schema_creation.sql и data_load.sql, како и
     426документацијата на Фаза 2, се ажурирани соодветно.
     427
     428=== Забелешка за постапката
     429
     430Кандидат клучевите и проверката за БКНФ не се одредени само со разгледување, туку
     431се пресметани програмски врз множеството функционални зависности (пресметка на
     432покривач на атрибути и проверка дали секоја детерминанта е суперклуч во секоја
     433релација). Токму таа проверка го откри нарушувањето кај Payment.
     434
     435== Користење на вештачка интелигенција
     436
     437 [wiki:NormalizationAIUsage NormalizationAIUsage]
     438
     439== Историјат
     440
     441 '''Верзија 1''' - Прва верзија на нормализацијата: денормализирана релација,
     442 функционални зависности, кандидат клучеви и декомпозиција до БКНФ и 4НФ.
     443 Откриено и отстрането нарушување на БКНФ во релацијата Payment.
     444
     445== Статус
     446
     447 ''' [[span(style=color: #FF8000, Во тек )]] '''