Функционални карактеристики и нормализација
Поделба на доменот според типот на евиденција
Поради комплексноста на моделот на базата, речиси е невозможно сите податоци да се стават во една табела. Затоа проблемот на нормализација ќе го поделиме на повеќе делови. Логичната поделба на табелите се заснова на улогите и процесите во системот: корисници, резервации, ресторани и мени производи.
Корисниците имаат директна интеракција со табелата reservations, а потоа може да се поврзат со tables и restaurants за да се добијат информации за ресторанот и масата што ја резервирале. Со тоа се формира агрегирана табела која може да ја наречеме: Резервации со корисници и маси
Релацијата е создадена за да ги поврзе информациите за масите со соодветните ресторани. Ова овозможува брз и ефикасен пристап до сите маси во даден ресторан.Маси и ресторани
Со оглед на разновидноста на менито и поврзаните тагови (на пример, кујна или тип на јадење), потребно е да се структурираат податоците на начин што ќе овозможи лесно филтрирање и пребарување. Мени и мени тагови
Со цел поефикасно следење на нарачките направени во текот на резервацијата, оваа релација ги поврзува преднарачаните производи со корисникот и резервацијата. Преднарачани производи (Preordered Items)
1. Oпределување на важечките функциски зависности
Тргнуваме од список во кој сите атрибути имаат различни имиња. За таа цел атрибутите кои што имаат исти имиња ги преименувавме. Во продолжение е списокот на атрибути кои што се преименувани.
- id (Кај ентитетот pre_ordered_items) -> preorderedItemId
- name (Кај ентитетот pre_ordered_items) -> preorderedItemName
- status (Кај ентитетот reservations) -> reservationStatus
- id (Кај ентитетот reservations) -> reservationHistoryId
- status (Кај ентитетот reservation_history) -> reservationStatus
- id (Кај ентиетот menu_tags) -> menuTagId
- id (Кај ентитетот users) -> userId
- category (Кај ентитетот menus) -> menuCategory
- location (Кај ентитетот tables) -> tableLocation
2. Резервации со корисници и маси
reservation_id | reservation_date | time_from | time_to | number_of_people | user_id | user_name | table_id | table_number | restaurant_id | restaurant_name | restaurant_location |
1 | 2025-05-01 | 18:00 | 20:00 | 4 | 101 | Ana | 11 | 1 | 201 | Gino’s | Skopje, Centar |
2 | 2025-05-02 | 19:30 | 21:00 | 2 | 102 | Marko | 12 | 2 | 202 | Sushico | Skopje, Karposh |
3 | 2025-05-03 | 17:00 | 18:30 | 3 | 103 | Elena | 13 | 3 | 203 | Bella Italia | Skopje, Aerodrom |
R = { reservation_id, reservation_date, time_from, time_to, number_of_people,
user_id, user_name,
table_id, table_number,
restaurant_id, restaurant_name, restaurant_location
}
Функциски зависности:
- reservation_id → reservation_date, time_from, time_to, number_of_people, user_id, table_id
- user_id → user_name
- table_id → table_number, restaurant_id
- restaurant_id → restaurant_name, restaurant_location
Лево:
reservation_id, user_id, table_id, restaurant_id
Само десно (зависни атрибути):
user_name, restaurant_name, restaurant_location, reservation_date, time_from, time_to, number_of_people, table_number
Кандидат клуч: reservation_id
Нормализација:
1НФ – Прва нормална форма: Сите атрибути се атомски.
2НФ – Втора нормална форма: Клучот reservation_id е едноставен, па нема парцијални зависности.
3НФ – Трета нормална форма: Имаме транзитивни зависности:
- reservation_id → table_id → restaurant_id → restaurant_name, restaurant_location
- reservation_id → user_id → user_name
Значи, атрибути зависат од не-примарен атрибут што зависи од клучот. Не е во 3НФ.
BCNF: Не е во BCNF бидејќи постојат функционски зависности каде детерминантата не е суперклуч.
- user_id → user_name
- table_id → restaurant_id
Декомпозицијa
R1:Reservation
{ reservation_id, reservation_date, time_from, time_to, number_of_people, user_id, table_id }
(во BCNF – клуч reservation_id)
R2:User
{ user_id, user_name }
(во BCNF – клуч user_id)
R3: Table
{ table_id, table_number, restaurant_id }
(во BCNF - клуч table_id)
R4: Restaurant
{ restaurant_id, restaurant_name, restaurant_location }
(во BCNF – клуч restaurant_id)
3. Маси и ресторани
table_id | table_number | restaurant_id | restaurant_name | restaurant_location |
11 | 1 | 201 | Gino’s | Skopje, Centar |
12 | 2 | 202 | Sushico | Skopje, Karposh |
13 | 3 | 203 | Bella Italia | Skopje, Aerodrom |
R= { table_id, table_number, restaurant_id, restaurant_name, restaurant_location }
Функциски зависности:
- table_id → table_number, restaurant_id
- restaurant_id → restaurant_name, restaurant_location
Лево:
table_id, restaurant_id
Само десно (зависни атрибути):
table_number, restaurant_name, restaurant_location
Кандидат клуч: table_id
Нормализација:
1НФ – Прва нормална форма:Сите атрибути се атомски.
2НФ – Втора нормална форма: Клучот table_id е едноставен, па нема парцијални зависности.
3НФ – Трета нормална форма: Имаме транзитивни зависности:
- table_id → restaurant_id → restaurant_name, restaurant_location
Значи, атрибути зависат од не-примарен атрибут што зависи од клучот. Не е во 3НФ.
BCNF: Не е во BCNF бидејќи постојат функционски зависности каде детерминантата не е суперклуч.
- restaurant_id → restaurant_name, restaurant_location
Декомпозиција
R1: Table
{ table_id, table_number, restaurant_id }
(во BCNF – клуч table_id)
R2: Restaurant
{ restaurant_id, restaurant_name, restaurant_location }
(во BCNF – клуч restaurant_id)
4. Мени и мени тагови
menu_id | menu_name | price | restaurant_id | restaurant_name | tag_id | tag_name |
1 | Margarita Pizza | 400 | 201 | Gino’s | 1 | Italian |
2 | California Roll | 550 | 202 | Sushico | 2 | Japanese |
3 | Carbonara | 470 | 201 | Gino’s | 1 | Italian |
4 | Tiramisu | 300 | 201 | Gino’s | 3 | Dessert |
R = { menu_id, menu_name, price, restaurant_id, restaurant_name, tag_id, tag_name }
Функциски зависности:
- menu_id → menu_name, price, restaurant_id, priceHistory_id
- restaurant_id → restaurant_name
- tag_id → tag_name
Левo:
- menu_id, restaurant_id, tag_id
Десни атрибути (оние што се зависни):
- menu_name, price, restaurant_name, tag_name
Кандидат клуч:
- menu_id (го одредува скоро сè)
Нормализација:
1НФ – Прва нормална форма: Сите атрибути се атомски
2НФ – Втора нормална форма Клучот menu_id е едноставен, нема парцијални зависности
3НФ – Трета нормална форма Постојат транзитивни зависности
- menu_id → restaurant_id → restaurant_name
- menu_id → tag_id → tag_name
BCNF
- restaurant_id и tag_id се детерминанти, а не се суперклучеви.
Декомпозиција
R1:Menu
{ menu_id, menu_name, price, restaurant_id, tag_id }
R2:Restaurant
{ restaurant_id, restaurant_name }
R3:MenuTag
{ tag_id, tag_name }
R4:PriceHistory
{ priceHistory_id, menu_id, old_price, change_date }
5. Преднарачани производи (Preordered Items) со мени и резервација
preordered_item_id | quantity | reservation_id | reservation_date | user_id | user_name | menu_id | menu_name | price |
1 | 2 | 1 | 2025-05-01 | 101 | Ana | 1 | Margarita Pizza | 400 |
2 | 1 | 2 | 2025-05-02 | 102 | Marko | 2 | California Roll | 550 |
3 | 3 | 3 | 2025-05-03 | 103 | Elena | 3 | Carbonara | 470 |
R = { preordered_item_id, quantity, reservation_id, reservation_date, user_id, user_name, menu_id, menu_name, price }
Функциски зависности:
- preordered_item_id → quantity, reservation_id, menu_id
- reservation_id → reservation_date, user_id
- user_id → user_name
- menu_id → menu_name, price
Лево:
- preordered_item_id, reservation_id, user_id, menu_id
Само десно (зависни атрибути):
- quantity, reservation_date, user_name, menu_name, price
Нормализација: 1НФ – Прва нормална форма Сите податоци се атомски и неделиви.
2НФ – Втора нормална формаKлучот е едноставен (preordered_item_id), нема парцијални зависности.
Трета нормална форма имаме транзитивни зависности:
- preordered_item_id → reservation_id → user_id → user_name
- preordered_item_id → menu_id → menu_name, price
BCNF Имаме детерминанти како reservation_id и menu_id кои не се суперклучеви во целата релација.
Декомпозиција:
R1:Preordred_Item
{ preordered_item_id, quantity, reservation_id, menu_id }
R2: Reservation
{ reservation_id, reservation_date, user_id }
R3: User
{ user_id, user_name }
R4: Menu
{ menu_id, menu_name, price }
Дискусија
Релацијата(Резервации со корисници и маси) ги инкорпорира сите потребни податоци за една резервација, но ја нарушува нормалната форма поради транзитивна зависност. Oва води до повторување на информации – ист корисник или ресторан ќе се појавува повеќепати, што го зголемува ризикот од несогласување на податоци (на пример, корисникот ќе има различни имиња во различни редови ако се направи грешка).
Декомпозицијата ја разрешува оваа слабост. Преку изолирање на ентитетите User, Table, и Restaurant, се постигнува структурен и логички интегритет на базата, овозможувајќи:
- Лесно ажурирање на корисник или ресторан без влијание врз резервациите
Резервации со корисници и маси
- R1(reservation_id, reservation_date, time_from, time_to, number_of_people, user_id, table_id)
- R2(user_id, user_name)
- R3(table_id, table_number, restaurant_id)
- R4(restaurant_id, restaurant_name, restaurant_location)
Оваа табела претставува типичен пример каде што еден ресторан има повеќе маси. Без нормализација, информациите за ресторанот се повторуваат за секоја маса, што има неколку проблеми:
- Се троши повеќе простор во базата.
- Може да дојде до грешки – на пример, ист ресторан да се внесе со различно име кај различни маси.
Со нормализацијата, се одвојуваат податоците за масите од податоците за рестораните, што носи повеќе предности:
- Aко се смени име или локација, се менува на едно место.
- Полесно се додаваат нови информации
Маси и ресторани
- R1(table_id, table_number, restaurant_id)
- R2(restaurant_id, restaurant_name, restaurant_location)
Некои атрибути се повторуваат – на пример името на ресторан или името на тагот. Тоа создава вишок(редундантност) и ризик од неконзистентност.
Со нормализација, ги раздвојуваме работите логично:
Менито го врзуваме со ресторан и со категорија (таг),
А името на ресторанот и името на категоријата ги чуваме само еднаш, посебно.
Воведување на табела priceHistory:
- history_id: Примарен клуч, автоматски генериран.
- menu_id: Надворешен клуч кој се поврзува со табелата Menu.
- price: Цената што важела во тој временски период.
- valid_from: Време кога цената започнала да важи.
- valid_to: Време кога цената престанала да важи (NULL ако е тековната цена).
Целта на оваа табела е да се зачуваат претходните цени на артиклите од менито кога тие ќе се променат. Секој пат кога ќе се ажурира цената на артикл, автоматски ќе се снима старата цена во табелата priceHistory.
Мени и мени тагови
- R1(menu_id, menu_name, price, restaurant_id, tag_id)
- R2(restaurant_id, restaurant_name)
- R3(tag_id, tag_name)
Во оваа релација(Преднарачани производи) се следи кои производи (од мени) биле однапред нарачани за конкретна резервација. Но со тоа што во една табела ги имаме и податоците за корисникот, резервацијата и производот, се појавуваат вишоци. Пример: исто мени или исто корисничко име може да се повторува.
Со нормализација ја раздвојуваме секоја логична целина:
Preordered_Item знае што и колку е однапред нарачано,
Menu знае што е тоа што се нуди,
Reservation води евиденција за кога и кој,
User ги чува податоците за корисниците.
Воспоставување врска меѓу PreorderedItems и Menu:
Оваа врска ќе овозможи прецизно следење на тоа кој артикл точно е однапред нарачан. Врската ќе обезбеди целосна интеграција на податоците при ажурирање на цените и прикажување на историски податоци.
Преднарачани производи (Preordered Items) со мени и резервација
- R1(preordered_item_id, quantity, reservation_id, menu_id)
- R2(reservation_id, reservation_date, user_id)
- R3(user_id, user_name)
- R4(menu_id, menu_name, price)