| 2 | | За табелите од нашата база на податоци, со цел разликување на самите id за секој ентитет, ќе ги преименуваме id атрибутите во <име_на_релација>_id. Со тоа добиваме: user_id, non_admin_user_id, admin_id, listener_id, musical_entity_id, song_id, artist_id, event_id, album_id, playlist_id. |
| 3 | | |
| 4 | | === Функционални зависности |
| 5 | | **user_id** -> profile_photo, email, username, full_name, password[[br]] |
| 6 | | **musical_entity_id** -> title, genre, release_date, artist_id[[br]] |
| 7 | | **song_id** -> link, album_id[[br]] |
| 8 | | **playlist_id** -> cover, playlist_name, listener_id[[br]] |
| 9 | | **event_id** -> event_name, location, venue, date, time, artist_id, admin_id[[br]] |
| 10 | | **(artist_id, musical_entity_id)** -> role[[br]] |
| 11 | | **(listener_id, musical_entity_id)** -> grade, comment[[br]] |
| 12 | | **(listener_id, song_id)** -> timestamp[[br]] |
| 13 | | **non_admin_user_id** -> /[[br]] |
| 14 | | **admin_id** -> /[[br]] |
| 15 | | **listener_id** -> /[[br]] |
| 16 | | **artist_id** -> /[[br]] |
| 17 | | **album_id** -> /[[br]] |
| 18 | | **(listener_id, playlist_id)** -> /[[br]] |
| 19 | | **(playlist_id, song_id)** -> /[[br]] |
| 20 | | **(follower_id, followee_id)** -> /[[br]] |
| 21 | | **(event_id, artist_id)** -> /[[br]] |
| 22 | | **(listener_id, musical_entity_id)** -> /[[br]] |
| 23 | | |
| 24 | | **Лево:**[[br]] |
| 25 | | user_id,[[br]] |
| 26 | | musical_entity_id,[[br]] |
| 27 | | song_id,[[br]] |
| 28 | | playlist_id,[[br]] |
| 29 | | event_id,[[br]] |
| 30 | | non_admin_user_id,[[br]] |
| 31 | | follower_id,[[br]] |
| 32 | | followee_id[[br]] |
| 33 | | |
| 34 | | |
| 35 | | **Десно:**[[br]] |
| 36 | | profile_photo, email, username, full_name, password,[[br]] |
| 37 | | title, genre, release_date, link, cover, playlist_name,[[br]] |
| 38 | | event_name, location, venue, date, time, role, grade, comment,[[br]] |
| 39 | | timestamp[[br]] |
| 40 | | |
| 41 | | **Лево и десно:**[[br]] |
| 42 | | artist_id, [[br]] |
| 43 | | admin_id,[[br]] |
| 44 | | listener_id, [[br]] |
| 45 | | album_id[[br]] |
| 46 | | |
| 47 | | **Глобална релација** [[br]] |
| 48 | | **R**={ user_id, musical_entity_id, song_id, playlist_id, event_id, non_admin_user_id, |
| 49 | | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| 50 | | title, genre, release_date, link, cover, playlist_name, event_name, location, venue, |
| 51 | | date, time, role, grade, comment, timestamp, artist_id, admin_id, listener_id, |
| 52 | | album_id } |
| 53 | | |
| 54 | | == Покривачи |
| 55 | | 1. **user_id+** = {user_id, profile_photo, email, username, full_name, password} -> **Не ги содржи сите атрибути** |
| 56 | | 2. **musical_entity_id+** = {musical_entity_id, title, genre, release_date, artist_id, role} -> **Не ги содржи сите атрибути** |
| 57 | | 3. **song_id+** = {song_id, link} -> **Не ги содржи сите атрибути** |
| 58 | | 4. **playlist_id+** = {playlist_id, cover, playlist_name, listener_id} -> **Не ги содржи сите атрибути** |
| 59 | | 5. **event_id+** = {event_id, event_name, location, venue, date, time, artist_id, admin_id} -> **Не ги содржи сите атрибути** |
| 60 | | 6. **non_admin_user_id+** = {non_admin_user_id} -> **Не ги содржи сите атрибути** |
| 61 | | 7. **follower_id+** = {follower_id} -> **Не ги содржи сите атрибути** |
| 62 | | 8. **followee_id+** = {followee_id} -> **Не ги содржи сите атрибути** |
| 63 | | |
| 64 | | ==== Ги комбинираме покривачите за да дојдеме до сите атрибути: |
| 65 | | 1. **{user_id, musical_entity_id}+** = {user_id,musical_entity_id, profile_photo, email, username, full_name, password, title, genre, release_date, artist_id, role} -> **Не ги содржи сите атрибути** |
| 66 | | |
| 67 | | 2. **{user_id, musical_entity_id, song_id}+** = {user_id, musical_entity_id, song_id, profile_photo, email, username, full_name, password, title, genre, release_date, artist_id, role, link, album_id} -> **Не ги содржи сите атрибути** |
| 68 | | |
| 69 | | 3. **{user_id, musical_entity_id, song_id, playlist_id }+** = {user_id, musical_entity_id, song_id, playlist_id, profile_photo, email, username, full_name, password, title, genre, release_date, artist_id, role , link, album_id, cover, playlist_name, listener_id, grade, comment, timestamp } -> **Не ги содржи сите атрибути** |
| 70 | | |
| 71 | | |
| 72 | | 4. **{user_id, musical_entity_id, song_id, playlist_id, event_id }+** = {user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, admin_id, profile_photo, email, username, full_name, password,title, genre, release_date, role , link, album_id,cover, playlist_name, listener_id, grade, comment, timestamp,event_name, location, venue, date, time} -> **Не ги содржи сите атрибути** |
| 73 | | |
| 74 | | 5. **{user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id}+** = {user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, profile_photo, email, username, full_name, password,title, genre, release_date, role, link, album_id, cover, playlist_name, listener_id, grade, comment, timestamp, event_name, location, venue, date, time, admin_id } -> **Не ги содржи сите атрибути** |
| 75 | | |
| 76 | | 6. **{user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, follower_id}+** = {user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, follower_id, profile_photo, email, username, full_name, password,title, genre, release_date, role, link, album_id, cover, playlist_name, listener_id, grade, comment, timestamp, event_name, location, venue, date, time, admin_id } -> **Не ги содржи сите атрибути** |
| 77 | | |
| 78 | | |
| 79 | | 7. **{user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, follower_id, followee_id}+** = {user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, follower_id, followee_id, profile_photo, email, username, full_name, password,title, genre, release_date, role, link, album_idcover, playlist_name, listener_id, grade, comment, timestamp, event_name, location, venue, date, time, admin_id } -> **Не ги содржи сите атрибути** |
| 80 | | |
| 81 | | |
| 82 | | 8. **{user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, follower_id, followee_id, non_admin_user_id}+** = {user_id, musical_entity_id, song_id, playlist_id, event_id, follower_id, followee_id, non_admin_user_id, profile_photo, email, username, full_name, password,title, genre, release_date, role, link, album_id, artist_id, cover, playlist_name, listener_id, grade, comment, timestamp, event_name, location, venue, date, time, admin_id } -> **Ги содржи сите атрибути** |
| 83 | | |
| 84 | | **Избран примарен клуч: {user_id, musical_entity_id, song_id, playlist_id, event_id, artist_id, follower_id, followee_id, non_admin_user_id}**[[br]] |
| 85 | | Релацијата ја задоволува **1НФ**, но не ја задоволува **2НФ** поради постоење на парцијални зависности. |
| 86 | | |
| 87 | | == Декомпозиција во 2НФ |
| 88 | | |
| 89 | | Најпрво ги групираме атрибутите само според клучевите од кои зависат. |
| 90 | | |
| 91 | | 1. user_id-> profile_photo, email, username, full_name, password |
| 92 | | 2. musical_entity_id-> title, genre, release_date, artist_id |
| 93 | | 3. song_id-> link, album_id |
| 94 | | 4. playlist_id-> cover, playlist_name, listener_id |
| 95 | | 5. event_id-> event_name, location, venue, date, time, artist_id, admin_id |
| 96 | | |
| 97 | | == Декомпозиција во релации |
| | 2 | |
| | 3 | За табелите од нашата база на податоци, со цел разликување на самите id за секој ентитет, |
| | 4 | ќе ги преименуваме id атрибутите во <име_на_релација>_id. |
| | 5 | Со тоа добиваме: user_id, non_admin_user_id, admin_id, listener_id, |
| | 6 | musical_entity_id, song_id, artist_id, event_id, album_id, playlist_id |
| | 7 | |
| | 8 | == Функционални зависности: |
| 106 | | - (listener_id, song_id)-> timestamp |
| 107 | | |
| 108 | | **R1 - {user_id, profile_photo, email, username, full_name, password} -> BCNF** |
| 109 | | |
| 110 | | **R2 - {musical_entity_id, title, genre, release_date, artist_id} -> BCNF** |
| 111 | | |
| 112 | | **R3 - {song_id, link, album_id} -> BCNF** |
| 113 | | |
| 114 | | **R4 - {playlist_id, cover, playlist_name, listener_id} -> BCNF** |
| 115 | | |
| 116 | | **R5 - {event_id, event_name, location, venue, date, time, artist_id, admin_id} -> Не задоволува 3НФ** |
| 117 | | |
| 118 | | **R6 - {(artist_id, musical_entity_id), role} -> BCNF** |
| 119 | | |
| 120 | | **R7 - {(listener_id, musical_entity_id), grade, comment} -> BCNF** |
| 121 | | |
| 122 | | **R8 - {(listener_id, song_id), timestamp} -> BCNF** |
| 123 | | |
| 124 | | **R9 - {(follower_id, followee_id)} -> BCNF** |
| 125 | | |
| 126 | | **R10 - {(playlist_id, song_id)} -> BCNF** |
| 127 | | |
| 128 | | **R11 - {(listener_id, musical_entity_id)} -> BCNF** |
| 129 | | |
| 130 | | **R12 - {(listener_id, playlist_id)} -> BCNF** |
| 131 | | |
| 132 | | **R13 - {(event_id, artist_id)} -> BCNF** |
| 133 | | |
| 134 | | === Декомпозиција на R5 |
| 135 | | |
| 136 | | Поради транзитивната зависност во **R5 (venue -> location)**, поточно секој venue секогаш ќе ја има истата локација, |
| 137 | | правиме декомпозиција во две релации: |
| 138 | | - **R5.1 {event_id, event_name, venue, date, time, artist_id, admin_id}** |
| 139 | | - **R14 {venue, location}** |
| | 17 | |
| | 18 | |
| | 19 | - non_admin_user_id-> user_id |
| | 20 | - admin_id-> user_id |
| | 21 | - listener_id-> non_admin_user_id |
| | 22 | - artist_id-> non_admin_user_id |
| | 23 | - album_id-> musical_entity_id |
| | 24 | |
| | 25 | - (listener_id, playlist_id)-> / |
| | 26 | - (playlist_id, song_id)-> / |
| | 27 | - (follower_id, followee_id)-> / |
| | 28 | - (event_id, artist_id)-> / |
| | 29 | - (listener_id, musical_entity_id)-> / |
| | 30 | - (listener_id, song_id, timestamp)-> / |
| | 31 | |
| | 32 | |
| | 33 | Лево: |
| | 34 | - song_id, |
| | 35 | - playlist_id, |
| | 36 | - event_id, |
| | 37 | - follower_id, |
| | 38 | - followee_id, |
| | 39 | - timestamp |
| | 40 | |
| | 41 | |
| | 42 | Десно: |
| | 43 | - profile_photo, email, username, full_name, password, |
| | 44 | - title, genre, release_date, link, cover, playlist_name, |
| | 45 | - event_name, location, venue, date, time, role, grade, comment, |
| | 46 | - timestamp |
| | 47 | |
| | 48 | Лево и десно: |
| | 49 | - user_id, |
| | 50 | - musical_entity_id, |
| | 51 | - artist_id, |
| | 52 | - admin_id, |
| | 53 | - listener_id, |
| | 54 | - album_id |
| | 55 | |
| | 56 | |
| | 57 | |
| | 58 | 1. Глобална релација |
| | 59 | |
| | 60 | |
| | 61 | R={ user_id, musical_entity_id, song_id, playlist_id, event_id, non_admin_user_id, |
| | 62 | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| | 63 | title, genre, release_date, link, cover, playlist_name, event_name, location, venue, |
| | 64 | date, time, role, grade, comment, timestamp, artist_id, admin_id, listener_id, |
| | 65 | album_id } --32 |
| | 66 | |
| | 67 | |
| | 68 | Функционални зависности: |
| | 69 | - FD1: song_id-> musical_entity_id,link, album_id |
| | 70 | - FD2: playlist_id-> cover, playlist_name, listener_id |
| | 71 | - FD3: event_id-> event_name, location, venue, date, time, artist_id, admin_id |
| | 72 | - FD4: (artist_id, musical_entity_id)-> role |
| | 73 | - FD5: (listener_id, musical_entity_id)-> grade, comment |
| | 74 | |
| | 75 | - FD6: non_admin_user_id-> user_id |
| | 76 | - FD7: admin_id-> user_id |
| | 77 | - FD8: listener_id-> non_admin_user_id |
| | 78 | - FD9: artist_id-> non_admin_user_id |
| | 79 | - FD10: album_id-> musical_entity_id |
| | 80 | |
| | 81 | |
| | 82 | - FD11: (listener_id, playlist_id)-> / |
| | 83 | - FD12: (playlist_id, song_id)-> / |
| | 84 | - FD13: (follower_id, followee_id)-> / |
| | 85 | - FD14: (event_id, artist_id)-> / |
| | 86 | - FD15: (listener_id, musical_entity_id)-> / |
| | 87 | - FD16: (listener_id, song_id, timestamp)-> / |
| | 88 | - FD17: user_id -> profile_photo, email, username, full_name, password |
| | 89 | - FD18: musical_entity_id -> title, genre, release_date, artist_id |
| | 90 | |
| | 91 | - Покривачи |
| | 92 | |
| | 93 | |
| | 94 | 1. song_id+ = {song_id, musical_entity_id, link, album_id} -> Не ги содржи сите атрибути |
| | 95 | 2. playlist_id+ = {playlist_id, cover, playlist_name, listener_id} -> Не ги содржи сите атрибути |
| | 96 | 3. event_id+ = {event_id, event_name, location, venue, date, time, artist_id, admin_id} -> Не ги содржи сите атрибути |
| | 97 | 4. follower_id+ = {follower_id} -> Не ги содржи сите атрибути |
| | 98 | 5. followee_id+ = {followee_id} -> Не ги содржи сите атрибути |
| | 99 | 6. timestamp+ = {timestamp} -> Не ги содржи сите атрибути |
| | 100 | |
| | 101 | = Спојување Покривачи |
| | 102 | |
| | 103 | Бидејќи атрибутите кои се наоѓаат само на левата страна не може да се изведат на никој друг начин, |
| | 104 | тие мора да бидат дел од примарниот клуч. |
| | 105 | |
| | 106 | {song_id, |
| | 107 | playlist_id, |
| | 108 | event_id, |
| | 109 | follower_id, |
| | 110 | followee_id, |
| | 111 | timestamp}+ = {song_id, playlist_id, event_id, follower_id, followee_id, |
| | 112 | link, album_id, cover, playlist_name, listener_id, musical_entity_id |
| | 113 | event_name, location, venue, date, time, artist_id, admin_id, |
| | 114 | user_id, non_admin_user_id, |
| | 115 | profile_photo, email, username, full_name, password, |
| | 116 | title, genre, release_date, |
| | 117 | role, |
| | 118 | grade, comment, |
| | 119 | timestamp} |
| | 120 | |
| | 121 | Покривачот составен од сите атрибути кои се наоѓаат само од левата страна ги содржи |
| | 122 | сите атрибути на глобалната релација. Всушност тоа ни е и минимален суперклуч. |
| | 123 | Во нашиот случај ова ни е единствениот кандидат клуч, па оттаму |
| | 124 | тоа ни е и примарниот клуч на релацијата. |
| | 125 | |
| | 126 | |
| | 127 | |
| | 128 | |
| | 129 | |
| | 130 | Избран примарен клуч: {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 131 | |
| | 132 | Бидејќи релацијата не содржи повеќевредносни атрибути, |
| | 133 | неуникатни атрибути, вредности од различен домен за еден атрибут, |
| | 134 | а притоа секоја редица е уникатно определена преку примарниот клуч, |
| | 135 | ја задоволува 1НФ, |
| | 136 | но не ја задоволува 2НФ поради постоење на парцијални зависности. |
| | 137 | |
| | 138 | Идентификувани парцијални зависности што ја нарушуваат 2NF: |
| | 139 | FD1 -> musical_entity_id, link, album_id зависат само од song_id |
| | 140 | FD2 -> cover, playlist_name, listener_id зависат само од playlist_id |
| | 141 | FD3 -> event_name, location, venue, date, time, artist_id, admin_id зависат само од event_id |
| | 142 | |
| | 143 | |
| | 144 | |
| | 145 | |
| | 146 | == Декомпозиција во 2НФ |
| | 147 | |
| | 148 | Најпрво ги групираме атрибутите само според клучевите од кои зависат. |
| | 149 | |
| | 150 | - song_id-> musical_entity_id, link, album_id |
| | 151 | - playlist_id-> cover, playlist_name, listener_id |
| | 152 | - event_id-> event_name, location, venue, date, time, artist_id, admin_id |
| | 153 | |
| | 154 | == Декомпозиција во релации |
| | 155 | |
| | 156 | -- Dali mi treba i song_id i musical_entity_id? |
| | 157 | Songs(song_id, musical_entity_id, link, album_id) |
| | 158 | pk: song_id |
| | 159 | |
| | 160 | R1 = R - {link, album_id} |
| | 161 | R1 = {user_id, song_id, musical_entity_id, playlist_id, event_id, non_admin_user_id, |
| | 162 | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| | 163 | title, genre, release_date, cover, playlist_name, event_name, location, venue, |
| | 164 | date, time, role, grade, comment, timestamp, artist_id, admin_id, listener_id, |
| | 165 | } |
| | 166 | R1_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 167 | |
| | 168 | Lossless join: Релацијата може да се реконструира преку song_id |
| | 169 | Dependency preservation: FD1 е сочувана преку Songs |
| | 170 | |
| | 171 | ---------------------------------------------------------------------------------- |
| | 172 | Playlists(playlist_id, cover, playlist_name, listener_id) |
| | 173 | pk: playlist_id |
| | 174 | |
| | 175 | R2 = R1 - {cover, playlist_name, listener_id} |
| | 176 | R2 = {user_id, musical_entity_id, song_id, playlist_id, event_id, non_admin_user_id, |
| | 177 | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| | 178 | title, genre, release_date, event_name, location, venue, |
| | 179 | date, time, role, grade, comment, timestamp, artist_id, admin_id} |
| | 180 | R2_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 181 | |
| | 182 | Lossless join: Релацијата може да се реконструира преку playlist_id |
| | 183 | Dependency preservation: FD2 е сочувана преку Playlists |
| | 184 | |
| | 185 | ---------------------------------------------------------------------------------- |
| | 186 | |
| | 187 | Events(event_id, event_name, location, venue, date, time, artist_id, admin_id) |
| | 188 | pk: event_id |
| | 189 | |
| | 190 | R3 = R2 - {event_name, location, venue, date, time, artist_id, admin_id} |
| | 191 | R3 = {user_id, musical_entity_id, song_id, playlist_id, event_id, non_admin_user_id, |
| | 192 | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| | 193 | title, genre, release_date, role, grade, comment, timestamp} |
| | 194 | R3_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 195 | |
| | 196 | Lossless join: Релацијата може да се реконструира преку event_id |
| | 197 | Dependency preservation: FD3 е сочувана преку Events |
| 143 | | **R1 - Клуч: user_id и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 144 | | |
| 145 | | **R2 - Клуч: musical_entity_id и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 146 | | |
| 147 | | **R3 - Клуч: song_id и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 148 | | |
| 149 | | **R4 - Клуч: playlist_id и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 150 | | |
| 151 | | **R5.1 - Клуч: event_id и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 152 | | |
| 153 | | **R6 - Клуч: (artist_id, musical_entity_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 154 | | |
| 155 | | **R7 - Клуч: (listener_id, musical_entity_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 156 | | |
| 157 | | **R8 - Клуч: (listener_id, song_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 158 | | |
| 159 | | **R9 - Клуч: (follower_id, followee_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 160 | | |
| 161 | | **R10 - Клуч: (playlist_id, song_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 162 | | |
| 163 | | **R11 - Клуч: (listener_id, musical_entity_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 164 | | |
| 165 | | **R12 - Клуч: (listener_id, playlist_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 166 | | |
| 167 | | **R13 - Клуч: (event_id, artist_id) и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 168 | | |
| 169 | | **R14 - Клуч: venue и сите атрибути зависат директно само од него. Релацијата е во BCNF** |
| 170 | | |
| 171 | | |
| 172 | | == Финални релации во BCNF |
| 173 | | 1. **Users** {user_id, profile_photo, email, username, full_name, password} |
| 174 | | 2. **Musical_Entities** {musical_entity_id, title, genre, release_date, artist_id} |
| 175 | | 3. **Songs** {song_id, link, album_id} |
| 176 | | 4. **Playlists** {playlist_id, cover, playlist_name, listener_id} |
| 177 | | 5. **Events** {event_id, event_name, location, venue, date, time, artist_id, admin_id} |
| 178 | | 6. **Artist_Contributions** {artist_id, musical_entity_id, role} |
| 179 | | 7. **Reviews** {listener_id, musical_entity_id, grade, comment} |
| 180 | | 8. **Listens** {listener_id, song_id, timestamp} |
| 181 | | 9. **Follows** {follower_id, followee_id} |
| 182 | | 10. **Playlist_Songs** {playlist_id, song_id} |
| 183 | | 11. **Likes** {listener_id, musical_entity_id} |
| 184 | | 12. **Saved_Playlists** {listener_id, playlist_id} |
| 185 | | 13. **Performs_At** {event_id, artist_id} |
| 186 | | 14. **Venues** {venue, location} |
| 187 | | |
| 188 | | == Дискусија на разликите од моделот во Фаза P2 |
| 189 | | |
| 190 | | |
| 191 | | |
| 192 | | Процесот на нормализација го потврди концептуалниот дизајн од [[html(<a href="https://develop.finki.ukim.mk/projects/finkwave/wiki/RelationalDesign" ">Фаза 2</a>)]]. Ова значи |
| 193 | | дека ЕР дијаграмот е солидно сработен. Единствена нова релација која произлезе од |
| 194 | | нормализацијата е **R14 (Venues)**, од каде произлегува и функционалната зависност |
| 195 | | venue -> location |
| | 201 | |
| | 202 | |
| | 203 | 1. Songs(song_id, musical_entity_id, link, album_id) -> има транзитивна завизсност преку |
| | 204 | FD18: musical_entity_id -> title, genre, release_date, artist_id |
| | 205 | FD10: album_id-> musical_entity_id, |
| | 206 | |
| | 207 | |
| | 208 | Декомпозиција: |
| | 209 | Songs(song_id,link, album_id) |
| | 210 | pk: song_id (fk -> Musical_Entities) |
| | 211 | Musical_Entities(musical_entity_id, title, genre, release_date, artist_id) |
| | 212 | pk: musical_entity_id |
| | 213 | Albums(album_id) |
| | 214 | pk: album_id (fk -> Musical_Entities) |
| | 215 | |
| | 216 | R4 = R3 - {title, genre, release_date, musical_entity_id} |
| | 217 | |
| | 218 | R4 = {user_id, song_id, playlist_id, event_id, non_admin_user_id, |
| | 219 | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| | 220 | role, grade, comment, timestamp} |
| | 221 | R4_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 222 | |
| | 223 | Lossless join: Релацијата може да се реконструира преку song_id |
| | 224 | Dependency preservation: Задржани се FD1, FD10 и FD18 преку Songs, Albums, Musical_Entities |
| | 225 | |
| | 226 | 2. Playlists(playlist_id, cover, playlist_name, listener_id) -> задоволува 3НФ |
| | 227 | |
| | 228 | 3. Events(event_id, event_name, location, venue, date, time, artist_id, admin_id) -> задоволува 3НФ |
| | 229 | |
| | 230 | |
| | 231 | Релации: |
| | 232 | |
| | 233 | 1. Songs(song_id,link, album_id) |
| | 234 | 2. Musical_Entities(musical_entity_id, title, genre, release_date, artist_id) |
| | 235 | 3. Albums(album_id) |
| | 236 | 4. Playlists(playlist_id, cover, playlist_name, listener_id) |
| | 237 | 5. Events(event_id, event_name, location, venue, date, time, artist_id, admin_id) |
| | 238 | 6. R4 = {user_id, song_id, playlist_id, event_id, non_admin_user_id, |
| | 239 | follower_id, followee_id, profile_photo, email, username, full_name, password, |
| | 240 | role, grade, comment, timestamp} |
| | 241 | |
| | 242 | |
| | 243 | |
| | 244 | --- zavisi od da se smeni so opredelen od |
| | 245 | |
| | 246 | 4. FD17: R4 содржи атрибути кои зависат само од user_id, кој не е дел од примaрниот клуч -> нарушува 3НФ |
| | 247 | |
| | 248 | Users(user_id, profile_photo, email, username, full_name, password) |
| | 249 | pk: user_id |
| | 250 | R5 = R4 - {profile_photo, email, username, full_name, password} |
| | 251 | |
| | 252 | R5 = {user_id, song_id, playlist_id, event_id, non_admin_user_id, |
| | 253 | follower_id, followee_id, role, grade, comment, timestamp} |
| | 254 | |
| | 255 | R5_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 256 | Lossless join: Релацијата може да се реконстроуира преку user_id |
| | 257 | Dependency preservation: FD17 |
| | 258 | |
| | 259 | |
| | 260 | 5. FD6: R5 содржи user_id кој зависи од non_admin_user_id, кој не е примарен клуч |
| | 261 | Non_Admin_Users(user_id) |
| | 262 | |
| | 263 | |
| | 264 | R6 = R5 - {user_id} |
| | 265 | R6 = {song_id, playlist_id, event_id, non_admin_user_id, |
| | 266 | follower_id, followee_id, role, grade, comment, timestamp} |
| | 267 | R6_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 268 | |
| | 269 | Lossless join: Релацијата може да се реконстроуира преку non_admin_user_id |
| | 270 | Dependency preservation: FD6 |
| | 271 | |
| | 272 | 6. FD7: Admins(user_id)-> dali ova na primer treba da bide (admin_id, user_id)? Shto ke ni smeni toa? |
| | 273 | pk: user_id (fk -> Users) |
| | 274 | |
| | 275 | 7. FD8: non_admin_user_id зависи од listener_id што не е дел од примарниот клуч |
| | 276 | Listeners(non_admin_user_id) |
| | 277 | pk: non_admin_user_id (fk -> Non_Admin_Users) |
| | 278 | |
| | 279 | R7 = R6 - {non_admin_user_id} |
| | 280 | R7 = {song_id, playlist_id, event_id, |
| | 281 | follower_id, followee_id, role, grade, comment, timestamp} |
| | 282 | R7_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 283 | |
| | 284 | Lossless join: Релацијата може да се реконстроуира преку listener_id |
| | 285 | Dependency preservation: FD8 |
| | 286 | |
| | 287 | |
| | 288 | 8. FD9: non_admin_user_id зависи од artist_id што не е дел од примарниот клуч |
| | 289 | Artists(non_admin_user_id) |
| | 290 | pk: non_admin_user_id (fk -> Non_Admin_Users) |
| | 291 | |
| | 292 | 9. role зависи од (artist_id, musical_entity_id) што не е целиот примарен клуч |
| | 293 | Artist_Contributions(artist_id, musical_entity_id, role) |
| | 294 | pk(artist_id, musical_entity_id) (fk -> Artists, fk -> Musical_Entities) |
| | 295 | |
| | 296 | R8 = R7 - {role} |
| | 297 | R7 = {song_id, playlist_id, event_id, |
| | 298 | follower_id, followee_id, grade, comment, timestamp} |
| | 299 | R7_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 300 | |
| | 301 | Lossless join: Релацијата може да се реконстроуира преку song_id -> Musical_Entities |
| | 302 | Dependency preservation: FD4 |
| | 303 | |
| | 304 | 10. grade, comment зависат од (listener_id, musical_entity_id), што не е целиот примaрен клуч |
| | 305 | Reviews(listener_id, musical_entity_id) |
| | 306 | pk: (listener_id, musical_entity_id) (fk -> Listeners, fk -> Musical_Entities) |
| | 307 | |
| | 308 | R9 = R8 - {grade, comment} |
| | 309 | R9 = {song_id, playlist_id, event_id,follower_id, followee_id, timestamp} |
| | 310 | R9_pk = {song_id, playlist_id, event_id, follower_id, followee_id, timestamp} |
| | 311 | |
| | 312 | Lossless join: Релацијата може да се реконстроуира преку song_id -> Musical_Entities |
| | 313 | -- Како би било тука Lossless join, дали е можно бидејќи го отсртанивме listener_id |
| | 314 | Dependency preservation: FD5 |
| | 315 | |
| | 316 | -- Ако останат musical_entity_id, listener_id, admin_id, artist_id |
| | 317 | немаме како да стигнеме до истите релации, односно ќе имаме |
| | 318 | неклучни атрибути во глобалната релација. |
| | 319 | |
| | 320 | Relacii: |
| | 321 | 1. Songs(song_id,link, album_id) |
| | 322 | 2. Musical_Entities(musical_entity_id, title, genre, release_date, artist_id) |
| | 323 | 3. Albums(album_id) |
| | 324 | 4. Playlists(playlist_id, cover, playlist_name, listener_id) |
| | 325 | 5. Events(event_id, event_name, location, venue, date, time, artist_id, admin_id) |
| | 326 | 6. Users(user_id, profile_photo, email, username, full_name, password) |
| | 327 | 7. Non_Admin_Users(user_id) |
| | 328 | 8. Listeners(non_admin_user_id) |
| | 329 | 9. Admins(user_id) |
| | 330 | 10. Artist_Contributions(artist_id, musical_entity_id, role) |
| | 331 | 11. Reviews(listener_id, musical_entity_id) |
| | 332 | 12. R9 = {song_id, playlist_id, event_id, |
| | 333 | follower_id, followee_id, timestamp} |
| | 334 | |
| | 335 | |
| | 336 | == Декомпозиција на R9 |
| | 337 | |
| | 338 | Релацијата R9 ги содржи преостанатите атрибути кои |
| | 339 | формираат сложени примарни клучеви за меѓусебните врски на ентитетите. |
| | 340 | Бидејќи овие врски претставуваат независни повеќевредносни факти, |
| | 341 | ги декомпонираме во посебни релации (од FD11 до FD16). |
| | 342 | |
| | 343 | 1. Follows(follower_id, followee_id) |
| | 344 | pk: (follower_id, followee_id) (fk -> Non_Admin_Users, fk -> Non_Admin_Users) |
| | 345 | |
| | 346 | 2. Saved_Playlists(listener_id, playlist_id) |
| | 347 | pk: (listener_id, playlist_id) (fk -> Listeners, fk -> Playlists) |
| | 348 | |
| | 349 | 3. Playlist_Songs(playlist_id, song_id) |
| | 350 | pk: (playlist_id, song_id) (fk -> Playlists, fk -> Songs) |
| | 351 | |
| | 352 | 4. Performs_At(event_id, artist_id) |
| | 353 | pk: (event_id, artist_id) (fk -> Events, fk -> Artists) |
| | 354 | |
| | 355 | 5. Likes(listener_id, musical_entity_id) |
| | 356 | pk: (listener_id, musical_entity_id) (fk -> Listeners, fk -> Musical_Entities) |
| | 357 | |
| | 358 | 6. Listens (listener_id, song_id, timestamp) |
| | 359 | pk: (listener_id, song_id, timestamp) (fk -> Listeners, fk -> Songs) |
| | 360 | |
| | 361 | |
| | 362 | == Финални релации |
| | 363 | |
| | 364 | 1. Songs(song_id,link, album_id) -> BCNF |
| | 365 | 2. Musical_Entities(musical_entity_id, title, genre, release_date, artist_id) -> BCNF |
| | 366 | 3. Albums(album_id) -> BCNF |
| | 367 | 4. Playlists(playlist_id, cover, playlist_name, listener_id) -> BCNF |
| | 368 | 5. Events(event_id, event_name, location, venue, date, time, artist_id, admin_id) -> BCNF |
| | 369 | 6. Users(user_id, profile_photo, email, username, full_name, password) -> BCNF |
| | 370 | 7. Non_Admin_Users(user_id) -> BCNF |
| | 371 | 8. Listeners(non_admin_user_id) -> BCNF |
| | 372 | 9. Admins(user_id) -> BCNF |
| | 373 | 10. Artists(non_admin_user_id) -> BCNF |
| | 374 | 11. Artist_Contributions(artist_id, musical_entity_id, role) -> BCNF |
| | 375 | 12. Reviews(listener_id, musical_entity_id) -> BCNF |
| | 376 | 13. Follows(follower_id, followee_id) -> BCNF |
| | 377 | 14. Saved_Playlists(listener_id, playlist_id) -> BCNF |
| | 378 | 15. Playlist_Songs(playlist_id, song_id) -> BCNF |
| | 379 | 16. Performs_At(event_id, artist_id) -> BCNF |
| | 380 | 17. Likes(listener_id, musical_entity_id) -> BCNF |
| | 381 | 18. Listens (listener_id, song_id, timestamp) -> BCNF |
| | 382 | |
| | 383 | |
| | 384 | == Заклучок |
| | 385 | Ги добивме истите релации од Фаза 2. |