Changes between Version 2 and Version 3 of Normalization
- Timestamp:
- 08/24/25 15:30:59 (9 days ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Normalization
v2 v3 32 32 **Напомена: Во овој процес на дефинирање на Ф.З не се зема во обѕир постоечката шема, туку се дефинираат самостојно, без да го гледаме она што веќе постои. Тоа се прави со цел да се добијат сите можни релации кои би ја довеле шемата во нормализирана форма.** 33 33 1. Еден корисник се одликува со низа од атрибути, па она кое би го одредувало секој корисник би било соодветно неговиот user_id, а од десната страна би биле соодветно user_name, user_surname, email, password_hash, is_user_active, user_created_at. Но исто така email се употребува за најава на корисникот, по што тој може да биде исто така еден кандидат клуч за самиот корисник, па ни произлегува уште една функционална зависност која може да се дефинира. Со еден email може да се најде соодветно user_id, кој би ги нашол сите останати атрибути кои зависат од него (email во user_id во user_name/user_surname….) 34 user_id -> email, user_name, user_surname, password_hash, is_user_active, user_created_at35 34 36 email -> user_id 35 **user_id -> email, user_name, user_surname, password_hash, is_user_active, user_created_at** 36 37 **email -> user_id** 37 38 2. Една улога би имало соодветно идентификатори role_id, кој ќе идентификува role_name, а тој role_name би бил објаснет со некаков role_description. Ова го размислувам дека секој role_name би бил уникатен, сигурно не би имало 2 улоги со исто име а за различна намена, затоа би можело да развиеме следните 2 ф.з. 38 role_id -> role_name39 39 40 role_name -> role_description 40 **role_id -> role_name** 41 42 **role_name -> role_description** 41 43 3. За секој корисник, според постоечките атрибути би требало да постои некаков си профил, кој ќе се одредува со profile_id, а зависните од него би биле user_id бидејќи треба 1 профил да биде само на 1 корисник, потоа profile_created_at, исто така и role_id бидејќи секој профил би се одликувал со некаква улога во апликацијата и некаков username. Username не одговара да биде соодветно идентификатор, бидејќи нема никаква улога за најава и со тоа не е ставен да биде како уникат, туку само како репрезентативност на самиот кориснички профил, по што не би имале уште една друга функционална зависност. 1 профил одоговара на 1 корисник секогаш, затоа мора да ја додадеме и обратната врска за од корисник во профил. 42 profile_id -> user_id, role_id, profile_created_at, username43 44 44 user_id -> profile_id 45 **profile_id -> user_id, role_id, profile_created_at, username** 46 47 **user_id -> profile_id** 45 48 4. Еден лог би се идентификувал со свој идентификатор log_id, а функционално зависни од него би биле соодветно profile_id (за кој профил би се оденсувало), опис на акцијата (change_description) и кога е создаден истиот во база (changed_at) 46 log_id -> profile_id, change_description, changed_at 49 50 **log_id -> profile_id, change_description, changed_at** 47 51 5. Сесија на корисник или пребарување, се одликува соодветно со некој идентификатор session_id, а таа соодветно ги претставува атрибутите како user_id, но бидејќи за еден корисник може да има повеќе сесии, нема да ја вметнеме обратната релација. Таа има соодветно некаков filter_description и кога е пребарана (searched_at) 48 session_id -> user_id, filter_description, searched_at 52 53 **session_id -> user_id, filter_description, searched_at** 49 54 6. Една сесија на пребарување би можела да се експортира па би добиле соодветно export_id, кој предводи session_id, како се вика самата датотека, кој е форматот, кога се експортира и некакво сумаризирање. Една сесија може да се експортира повеќе пати, со различен формат на датотека или име и слично, но едно експортирање на сесијата може да биде само на таа сесија. Примарен клуч би било export_id, а forreign би било session_id. 50 export_id -> session_id, export_format, file_name, filter_summary, export_date 55 56 **export_id -> session_id, export_format, file_name, filter_summary, export_date** 51 57 7. Сега доаѓам до Person ентитет кој може да го истранам од самата мега релација, кој би имал 2 кандидат клучеви или embg бидејќи е уникатен за сите корисници, или пак person_id. ''Сметам дека матичниот број е уникатен, но ако размислиме малку подалеку, потои некаква веројатност да се случи 2 personi кои се регистрирани во апликацијата или би се регистрирале да се од различна земја, па нивните форматирања да се различни, но сепак да дојде до појава на 2 исти матични броеви (уникатни идентификатори за личноста). Па затоа, сметам дека поставувањето на матичниот број би било уникатно ако апликацијата би била направена доменски за македонски извештаи, а на ниво на истата може да се регистрираат било какви персони, по што embg не би бил одредувачи (кандидат клуч). Доклку би имале некој си country_code, тогаш комбиниран клуч {embg, country_code} би било опција за кандидат клуч, но во оваа апликација тоа го нема, па ќе се осврнеме на person_id.'' Еден персон би се одликувал со name, surname, gender, DOB, is_alive flag, date_of_death, address_of_living, contact_phone и embg би било одредувачко од person_id заедно со наведените атрибути. 52 person_id -> embg, name, surname, gender, date_of_birth, is_alive, date_of_death, address_of_living,contact_phone 58 59 **person_id -> embg, name, surname, gender, date_of_birth, is_alive, date_of_death, address_of_living,contact_phone** 53 60 8. Ќе продолжиме од оние сигурните ентитети, како што е Insitution. Би се одликувал со уникатен кандидат клуч institution_id, а би содржел institution_name, institution_address, city, type, year_established 54 institution_id -> institution_name, institution_address, city, type, year_established 61 62 **institution_id -> institution_name, institution_address, city, type, year_established** 55 63 9. Сега доаѓа на ред Report. Секој извештај како ентитет, има под-ентитет кој го претставува и има 1-1 релација со некој од 4те можни ентитети. Се креира извештај, се поставува неговиот тип, и тој носи креирање на под-ентите од соодветниот тип кој може да повлекува и некои други ентитети за да биде комплетиран. Тоа значи дека да тргнеме од report_id, може да дојдеме до 1 од 4те под-извештаи (Академски, Медицински, Работен, Криминален), но не може да гарантираме дека од СЕКОЕ report_id може да дојдеме до било кој од овие, бидејќи е во релација 1 <-> 1. 56 64 Генерички би било да постои Report кој се одликува со уникатно report_id, и атрибути кои се ф.з од тоа report_id како report_created_at, summary, потоа најважното кое ја прави магијата е report_type и person_id бидејќи секој извештај се однесува на некоја персона во базата на податоци, односно не може да се напише извештај конкретно во оваа апликација кој ќе се однесува на person_id = null. 57 report_id -> report_type, report_created_at, summary, person_id 65 66 **report_id -> report_type, report_created_at, summary, person_id** 58 67 10. ПРВИОТ ТИП НА ИЗВЕШТАЈ – КРИМИНАЛЕН ИЗВЕШТАЈ 59 68 Секој извештај би имал подтип кој го наследува технички генеричкиот Report со соодветниот тип за него. Во случајов креирањето на Report (report_type=criminal) 1<-> 1 !CriminalReport 60 69 Примарен клуч би бил report_id, кој воедно е и туѓ клуч, а атрибути кои треба да бидат одредени од него би биле location, resolved, за каков тип се однесува crime_type_id и descriptive_punishment, каде објаснето би било самата казна на криминалот. Исто така, еден тип на криминал може да има еден извештај за криминал, не и повеќе, па затоа се извлечени соодветно само тие две функционални зависности. 61 70 Типот на криминал ќе се одликува со severity_level и label 62 report_id -> location, resolved, crime_type_id, descriptive_punishment 63 crime_type_id -> severity_level, label 71 72 **report_id -> location, resolved, crime_type_id, descriptive_punishment** 73 74 **crime_type_id -> severity_level, label** 75 64 76 Тука ни е и самата казна, која има свој идентификатор punishment_id, но бидејќи е осмислено да има повеќе казни за еден криминал, по што во ентитетот на казната би припаднал туѓ клуч кон report_id (за кој извештај се однесува). Исто така, казните се дефинираат посебно за секој report, по што нема доделување на веќе постоечки казни за повеќе криминални извештаи. 65 77 Таа се одликува со value_unit, punishment_type, fine_to_pay, release_date, каде соодветно во зависност од типот на казна, се одредува вредносната единица и едното од release_date и fine_to_pay е соодветно пополнето, а другото null. Ова би се направило за да се задоволат потребите на апликацијата. 66 punishment_id -> report_id, value_unit, punishment_type, fine_to_pay, release_date 78 79 **punishment_id -> report_id, value_unit, punishment_type, fine_to_pay, release_date** 67 80 11. ВТОРИОТ ТИП НА ИЗВЕШТАЈ – АКАДЕМСКИ ИЗВЕШТАЈ 68 81 Report (report_type=academic) 1<-> 1 !AcademicReport 69 82 Исто така примарен клуч ќе е report_id, а ќе ги одредува соодветно academic_field, description_of_report и ќе биде поврзано со институција (institution_id) во која се одвивал процесот, соодветно затоа и би постоел единствено institution ентитетот, со тие атрибути. 70 report_id -> academic_field, institution_id, description_of_report (за institution_id -> …, веќе го дефиниравме во точка 8) 83 84 **report_id -> academic_field, institution_id, description_of_report (за institution_id -> …, веќе го дефиниравме во точка 8)** 71 85 12. ТРЕТИОТ ТИП НА ИЗВЕШТАЈ – РАБОТЕН ИЗВЕШТАЈ 72 86 Report (report_type=employment) 1<-> 1 !EmploymentReport 73 87 Атрибутите би биле start_date, end_date, job_role, income_per_month (релативно едноставен) 74 report_id -> start_date, end_date, job_role, income_per_month 88 89 **report_id -> start_date, end_date, job_role, income_per_month** 75 90 13. ЧЕТВРТИОТ ТИП НА ИЗВЕШТАЈ – МЕДИЦИНСКИ ИЗВЕШТАЈ 76 91 Report (report_type=medical) 1<-> 1 !MedicalReport 77 Секој извештај има свој уникатен report_id како и другите по горе наведени 3, а како атрибути кои се ф.з од него се соодветниот доктор кој го издал извештајот (референца до него преку doctor_id), потоа од преостанатите во релацијата би имал next_control_date и тоа во MedicalReport. 78 report_id -> next_control_date, doctor_id 92 Секој извештај има свој уникатен report_id како и другите по горе наведени 3, а како атрибути кои се ф.з од него се соодветниот доктор кој го издал извештајот (референца до него преку doctor_id), потоа од преостанатите во релацијата би имал next_control_date и тоа во !MedicalReport. 93 94 **report_id -> next_control_date, doctor_id** 95 79 96 Докторот си е свој ентите кој би имал doctor_name, doctor_surname, specialization, years_of_experience и is_active 80 doctor_id -> doctor_name, doctor_surname, specialization, years_of_experience, is_active 97 98 **doctor_id -> doctor_name, doctor_surname, specialization, years_of_experience, is_active** 99 81 100 Преостанува уште неколку атрибути од кои би се создале некои логички Ф.З. Соодветно, има нешто со дијагнози, па така би откриле дека постои некој ентитет Diagnosis, кој има свој идентификатор (diagnosis_id), потоа short_description, therapy, is_chronic и severity. 82 diagnosis_id -> short_description, therapy, is_chronic, severity 101 102 **diagnosis_id -> short_description, therapy, is_chronic, severity** 103 83 104 Бидејќи дијагнозите во светот на медицината релативно се повторуваат, веќе се видени повеќето, може да се дозволи меморирање на дијагнози во самата апликациска база кои ќе се РЕИСКОРИСТУВААТ и за други извештаи. Па затоа, мора да се создаде посебна табела, која би имало смисла да има секој ред посебно id, кое ќе одредува комбинација од 2 туѓи клуча – едниот report_id, а другиот назначената дијагноза diagnosis_id, и датум кога е додаден записот во табелата. 84 r_d_id -> diagnosis_id, report_id, added_on 105 106 **r_d_id -> diagnosis_id, report_id, added_on** 85 107 108 По процесот на издвојување на функционални зависности се добива следново: 109 * user_id -> email, user_name, user_surname, password_hash, is_user_active, user_created_at 110 * email -> user_id 111 * role_id -> role_name 112 * role_name -> role_description 113 * profile_id -> user_id, role_id, profile_created_at, username 114 * user_id -> profile_id 115 * log_id -> profile_id, change_description, changed_at 116 * session_id -> user_id, filter_description, searched_at 117 * export_id -> session_id, export_format, file_name, filter_summary, export_date 118 * person_id -> embg, name, surname, gender, date_of_birth, is_alive, date_of_death, address_of_living, contact_phone 119 * institution_id -> institution_name, institution_address, city, type, year_established 120 * report_id -> report_type, report_created_at, summary, person_id 121 * report_id -> location, resolved, crime_type_id, descriptive_punishment 122 * crime_type_id -> severity_level, label 123 * punishment_id -> report_id, value_unit, punishment_type, fine_to_pay, release_date 124 * report_id -> academic_field, institution_id, description_of_report 125 * report_id -> start_date, end_date, job_role, income_per_month 126 * report_id -> next_control_date, doctor_id 127 * doctor_id -> doctor_name, doctor_surname, specialization, years_of_experience, is_active 128 * diagnosis_id -> short_description, therapy, is_chronic, severity 129 * r_d_id -> diagnosis_id, report_id, added_on 130 131 **Атрибути кои се појавуваат [[span(style=color: #FF0000, само на левата страна (детерминанти))]]:** 132 133 { export_id, punishment_id, r_d_id, log_id } 134 135 **Атрибути кои се појавуваат [[span(style=color: #FF0000, само на десната страна (зависни/детерминирани))]]:** 136 137 { user_name, user_surname, password_hash, profile_created_at, username, filter_description, searched_at, export_format, file_name, filter_summary, export_date, embg, name, surname, gender, date_of_birth, is_alive, date_of_death, address_of_living, contact_phone, institution_name, institution_address, city, type, year_established, report_type, report_created_at, summary, location, resolved, descriptive_punishment, severity_level, label, value_unit, punishment_type, fine_to_pay, release_date, academic_field, description_of_report, start_date, end_date, job_role, income_per_month, next_control_date, doctor_name, doctor_surname, specialization, years_of_experience, short_description, therapy, is_chronic, severity, added_on, change_description, changed_at } 138 139 **Атрибути кои се појавуваат [[span(style=color: #FF0000, и од левата и од десната страна)]]:** 140 141 { user_id, email, role_id, role_name, profile_id, session_id, person_id, institution_id, report_id, crime_type_id, doctor_id, diagnosis_id } 142 143 Потребно е да најдеме покривач така што ги поврзуваме само оние вредности кои се одредуваат преку тој атрибут, а не сите вредности кои може да се стигне тргнувајќи од него. Тие се наоѓаат така што се тргнува од оние атрибути кои се само од левата страна. 144 145 ''Покривач - X+ = { сите атрибути што можат да се изведат од X преку дадените функционални зависиности }'' 146