| 10 | | - user_id-> profile_photo, email, username, full_name, password |
| 11 | | - musical_entity_id-> title, genre, release_date, artist_id |
| 12 | | - song_id-> musical_entity_id, link, album_id |
| 13 | | - playlist_id-> cover, playlist_name, listener_id |
| 14 | | - event_id-> event_name, location, venue, date, time, artist_id, admin_id |
| 15 | | - (artist_id, musical_entity_id)-> role |
| 16 | | - (listener_id, musical_entity_id)-> grade, comment |
| 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 } |
| 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 | | = Спојување Покривачи |
| | 8 | |
| | 9 | - FD1: user_id -> profile_photo, email, username, full_name, password |
| | 10 | - FD3: musical_entity_id -> title, genre, me_cover, release_date, artist_id |
| | 11 | - FD4: song_id -> link, album_id |
| | 12 | - FD5: playlist_id -> playlist_cover, playlist_name, listener_id |
| | 13 | - FD6: event_id -> event_name, location, venue, date, time, user_id |
| | 14 | - FD7: (artist_id, musical_entity_id) -> role |
| | 15 | - FD8: (listener_id, musical_entity_id) -> grade, comment |
| | 16 | |
| | 17 | - FD9: non_admin_user_id -> user_id |
| | 18 | - FD10: admin_id -> user_id |
| | 19 | - FD11: listener_id -> non_admin_user_id |
| | 20 | - FD12: artist_id -> non_admin_user_id |
| | 21 | - FD13: album_id -> musical_entity_id |
| | 22 | - FD14: (listener_id,song_id,timestamp) -> / |
| | 23 | |
| | 24 | |
| | 25 | **Лево**: |
| | 26 | playlist_id, event_id, song_id, timestamp, admin_id |
| | 27 | |
| | 28 | |
| | 29 | **Десно**: |
| | 30 | profile_photo, email, username, full_name, password, title, genre, release_date, me_cover, link, playlist_cover, playlist_name, event_name, location, venue, date, time, role, grade, comment |
| | 31 | |
| | 32 | **Лево и десно**: |
| | 33 | user_id, musical_entity_id, artist_id, non_admin_user_id, album_id, listener_id |
| | 34 | |
| | 35 | |
| | 36 | |
| | 37 | === Глобална релација |
| | 38 | |
| | 39 | R={ playlist_id, event_id, song_id, timestamp, admin_id, profile_photo, email, username, full_name, password, title, genre, release_date, me_cover, link, playlist_cover, playlist_name, event_name, location, venue, date, time, role, grade, comment, user_id, musical_entity_id, artist_id, non_admin_user_id, album_id, listener_id} |
| | 40 | |
| | 41 | |
| | 42 | == Покривачи |
| | 43 | |
| | 44 | |
| | 45 | 1. **playlist_id+** = {playlist_id, playlist_name, playlist_cover, listener_id, user_id, full_name, email, password, username, profile_photo} -> **Не ги содржи сите атрибути** |
| | 46 | 2. **event_id+** = {event_id, event_name, location, venue, date, time, user_id, full_name, email, password, username, profile_photo} -> **Не ги содржи сите атрибути** |
| | 47 | 3. **song_id+** = {song_id, link, album_id, musical_entity_id, title, genre, me_cover, release_date, artist_id, non_admin_user_id, user_id, full_name, email, password, username, profile_photo} -> **Не ги содржи сите атрибути** |
| | 48 | 4. **timestamp+** = {timestamp} -> **Не ги содржи сите атрибути** |
| | 49 | 5. **admin_id+** = {admin_id, user_id, full_name, email, password, username, profile_photo } -> **Не ги содржи сите атрибути** |
| | 50 | |
| | 51 | |
| | 52 | |
| | 53 | == Спојување Покривачи |
| 156 | | |
| 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 |
| | 87 | 1. **Playlists(playlist_id, playlist_name, playlist_cover, listener_id)** |
| | 88 | |
| | 89 | R1 = R - {playlist_name, playlist_cover} |
| | 90 | |
| | 91 | R1 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, full_name, email, password, username, profile_photo, event_name, location, venue, date, time, link, album_id, musical_entity_id, title, genre, me_cover, release_date, artist_id, non_admin_user_id, role, grade, comment} |
| | 92 | |
| | 93 | Lossless join: Релацијата може да се реконструира преку join со `playlist_id`. |
| | 94 | |
| | 95 | Dependency preservation: FD5 е сочувана преку новата релација `Playlists`. |
| | 96 | |
| | 97 | |
| | 98 | 2. **Songs(song_id, link, album_id)** |
| | 99 | |
| | 100 | R2 = R1 - {link} |
| | 101 | |
| | 102 | R2 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, full_name, email, password, username, profile_photo, event_name, location, venue, date, time,musical_entity_id, title, genre, me_cover, release_date, artist_id,non_admin_user_id, role, grade, comment} |
| | 103 | |
| | 104 | Lossless join: Релацијата може да се реконструира преку join со `song_id` |
| | 105 | |
| | 106 | Dependency preservation: FD4 е сочувана преку новата релација `Songs` |
| | 107 | |
| | 108 | |
| | 109 | 3. **Events(event_id, event_name, location, venue, date, time, user_id)** |
| | 110 | |
| | 111 | R3 = R2 - {event_name, location, venue, date, time} |
| | 112 | |
| | 113 | R3 = {playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, full_name, email, password, username, profile_photo, musical_entity_id, title, genre, me_cover, release_date, artist_id, non_admin_user_id, role, grade, comment} |
| | 114 | |
| | 115 | Lossless join: Релацијата може да се реконструира преку join со `event_id` |
| | 116 | |
| | 117 | Dependency preservation: FD6 е сочувана преку новата релација `Events` |
| | 118 | |
| | 119 | |
| | 120 | 4. **Admins(admin_id, user_id)** |
| | 121 | |
| | 122 | Lossless join: Релацијата може да се реконструира преку join со `admin_id` |
| | 123 | |
| | 124 | Dependency preservation: FD10 е сочувана преку новата релација `Admins` |
| | 125 | |
| | 126 | |
| | 127 | |
| | 128 | Добиени релации: |
| | 129 | 1. Playlists(playlist_id, playlist_name, playlist_cover, listener_id) |
| | 130 | 2. Songs(song_id, link, album_id) |
| | 131 | 3. Events(event_id, event_name, location, venue, date, time, user_id) |
| | 132 | 4. Admins(admin_id, user_id) |
| | 133 | 5. R3 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, full_name, email, password, username, profile_photo, musical_entity_id, title, genre, me_cover, release_date, artist_id, non_admin_user_id, role, grade, comment } |
| | 134 | |
| | 135 | |
| 200 | | |
| 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 | | |
| 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 | | |
| 314 | | Dependency preservation: FD5 |
| 315 | | |
| 316 | | |
| 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 |
| | 138 | Поради постоењето на транзитивни зависности во добиените релации, можеме да заклучиме дека **е нарушена 3НФ**. На пример: `Playlists(playlist_id, playlist_name, playlist_cover, listener_id)` има транзитивна зависност преку `FD11: listener_id -> non_admin_user_id` |
| | 139 | |
| | 140 | == Декомпозиција по 3НФ |
| | 141 | |
| | 142 | 1. `Playlists(playlist_id, playlist_name, playlist_cover, listener_id)` -> има транзитивна зависност преку `FD11: listener_id -> non_admin_user_id` |
| | 143 | |
| | 144 | Декомпозиција по FD11: |
| | 145 | |
| | 146 | **Listeners(listener_id, non_admin_user_id)** -> има транзитивна зависност преку `FD9: non_admin_user_id -> user_id` |
| | 147 | |
| | 148 | Декомпозиција по FD9: |
| | 149 | |
| | 150 | **Non_Admin_Users(non_admin_user_id, user_id)** |
| | 151 | |
| | 152 | **Listeners(listener_id)** - `listener_id` е всушност примарен клуч во релацијата `Listeners` и надворешен клуч во релацијата `Non_Admin_Users`; |
| | 153 | |
| | 154 | `Non_Admin_Users(non_admin_user_id, user_id)` -> има транзитивна зависност преку `FD1: user_id -> profile_photo, email, username, full_name, password` |
| | 155 | |
| | 156 | Декомпозиција по FD1: |
| | 157 | |
| | 158 | **Users(user_id, profile_photo, email, username, full_name, password)** |
| | 159 | |
| | 160 | `Non_Admin_Users(non_admin_user_id)` - `non_admin_user_id` е всушност примарен клуч во релацијата `Non_Admin_Users` и надворешен клуч во релацијата `Users` |
| | 161 | |
| | 162 | R4 = R3 - {profile_photo, email, username, full_name, password} |
| | 163 | R4 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, musical_entity_id, title, genre, me_cover, release_date, artist_id, non_admin_user_id, role, grade, comment} |
| | 164 | |
| | 165 | Lossless join: Релацијата може да се реконструира преку join со `user_id` |
| | 166 | |
| | 167 | Dependency preservation: FD1 е сочувана преку новата релација `Users` |
| | 168 | |
| | 169 | 2. `Songs(song_id, link, album_id)` -> има транзитивна зависност преку `FD13: album_id -> musical_entity_id` |
| | 170 | |
| | 171 | Декомпозиција по FD13: |
| | 172 | |
| | 173 | **Albums(album_id, musical_entity_id)** -> има транзитивна преку `FD3: musical_entity_id-> title, genre, me_cover, release_date, artist_id` |
| | 174 | |
| | 175 | Lossless join: Релацијата може да се реконструира преку join со `album_id` |
| | 176 | |
| | 177 | Dependency preservation: FD13 е сочувана преку новата релација `Albums` |
| | 178 | |
| | 179 | Декомпозиција по FD3: |
| | 180 | |
| | 181 | **Musical_Entities(musical_entity_id, title, genre, me_cover, release_date, artist_id)** |
| | 182 | |
| | 183 | `Albums(album_id)` - `album_id` е всушност примарен клуч во релацијата `Albums` и надворешен клуч во релацијата `Musical_Entities`. |
| | 184 | |
| | 185 | R5 = R4 - {title, genre, me_cover, release_date} |
| | 186 | |
| | 187 | R5 = { playlist_id, event_id, song_id, timestamp, admin_id,user_id, listener_id, album_id, musical_entity_id, artist_id, non_admin_user_id, role, grade, comment} |
| | 188 | Lossless join: Релацијата може да се реконструира преку join со `musical_entity_id` |
| | 189 | |
| | 190 | Dependency preservation: FD3 е сочувана преку новата релација `Musical_Entities` |
| | 191 | |
| | 192 | `Musical_Entities(musical_entity_id, title, genre, me_cover, release_date, artist_id)` -> има транзитивна зависност преку `FD12: artist_id -> non_admin_user_id` |
| | 193 | |
| | 194 | Декомпозиција по FD12: |
| | 195 | |
| | 196 | **Artists(artist_id)** - `artist_id` е всушност примарен клуч во релацијата `Artists` и надворешен клуч во релацијата `Non_Admin_Users`, каде е надворешен клуч во релацијата `Users`. Сите останати релации се добиени преку претходните декомпозиции. |
| | 197 | |
| | 198 | |
| | 199 | 3. `Events(event_id, event_name, location, venue, date, time, user_id)` -> има транзитивна зависност преку FD1, но веќе направивме декомпозиција по FD1. |
| | 200 | |
| | 201 | 4. `Admins(admin_id, user_id)` -> има транзитивна зависност преку FD1 и бидејќи `admin_id` е |
| | 202 | примарен клуч во `Admins` и надворешен клуч во `Users`, ја реформираме релацијата: |
| | 203 | |
| | 204 | **Admins(admin_id)**, каде `admin_id` е надворешен клуч во табелата `Users`. |
| | 205 | |
| | 206 | |
| | 207 | Добиени релации: |
| | 208 | |
| | 209 | 1. Playlists(playlist_id, playlist_name, playlist_cover, listener_id) |
| | 210 | 2. Songs(song_id, link, album_id) |
| | 211 | 3. Events(event_id, event_name, location, venue, date, time, user_id) |
| | 212 | 4. Admins(admin_id) |
| | 213 | 5. Listeners(listener_id) |
| | 214 | 6. Non_Admin_Users(non_admin_user_id) |
| | 215 | 7. Users(user_id, profile_photo, email, username, full_name, password) |
| | 216 | 8. Albums(album_id) |
| | 217 | 9. Musical_Entities(musical_entity_id, title, genre, me_cover, release_date, artist_id) |
| | 218 | 10. Artists(artist_id) |
| | 219 | 11. R5 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, musical_entity_id, artist_id, non_admin_user_id, role, grade, comment} |
| | 220 | |
| | 221 | |
| | 222 | 5. Бидејќи `role` е определен од `(artist_id, musical_entity_id)` -> имаме транзитивна зависност преку `FD7:(artist_id, musical_entity_id) -> role` |
| | 223 | |
| | 224 | Декомпозиција по FD7: |
| | 225 | |
| | 226 | **Artist_Contributions(artist_id, musical_entity_id, role)** |
| | 227 | |
| | 228 | R6 = R5 - {role} |
| | 229 | R6 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, musical_entity_id, artist_id, non_admin_user_id, grade, comment} |
| | 230 | |
| | 231 | Lossless join: Релацијата може да се реконструира преку join со `(artist_id, musical_entity_id)` |
| | 232 | |
| | 233 | Dependency preservation: FD7 е сочувана преку новата релација `Musical_Entities` |
| | 234 | |
| | 235 | 6. Бидејќи `grade`, `comment` се определени од `(listener_id, musical_entity_id)` -> имаме транзитивна зависност преку `FD8: (listener_id, musical_entity_id) -> grade, comment` |
| | 236 | |
| | 237 | Декомпозиција по FD8: |
| | 238 | |
| | 239 | **Reviews(listener_id, musical_entity_id, grade, comment)** |
| | 240 | R7 = R6 - {grade, comment} |
| | 241 | R7 = { playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, musical_entity_id, artist_id, non_admin_user_id} |
| | 242 | |
| | 243 | Lossless join: Релацијата може да се реконструира преку join со `(listener_id, musical_entity_id)`. |
| | 244 | |
| | 245 | Dependency preservation: FD8 е сочувана преку новата релација `Reviews`. |
| | 246 | |
| | 247 | |
| | 248 | == Проверка за БКНФ: |
| | 249 | |
| | 250 | Примарните клучеви се болдирани. |
| | 251 | |
| | 252 | 1. Playlists(**playlist_id**, playlist_name, playlist_cover, listener_id) -> **задоволува БКНФ** |
| | 253 | 2. Songs(**song_id**, link, album_id) -> **задоволува БКНФ** |
| | 254 | 3. Events(**event_id**, event_name, location, venue, date, time, user_id) -> **задоволува БКНФ** |
| | 255 | 4. Admins(**admin_id**) -> **задоволува БКНФ** |
| | 256 | 5. Listeners(**listener_id**) -> **задоволува БКНФ** |
| | 257 | 6. Non_Admin_Users(**non_admin_user_id**) -> **задоволува БКНФ** |
| | 258 | 7. Users(**user_id**, profile_photo, email, username, full_name, password) -> **задоволува БКНФ** |
| | 259 | 8. Albums(**album_id**) -> **задоволува БКНФ** |
| | 260 | 9. Musical_Entities(**musical_entity_id**, title, genre, me_cover, release_date, artist_id) -> **задоволува БКНФ** |
| | 261 | 10. Artist_Contributions(**artist_id, musical_entity_id**, role) -> **задоволува БКНФ** |
| | 262 | 11. Reviews(**listener_id, musical_entity_id**, grade, comment) -> **задоволува БКНФ** |
| | 263 | 12. Artists(**artist_id**) -> **задоволува БКНФ** |
| | 264 | 13. R7 = { **playlist_id, event_id, song_id, timestamp, admin_id, user_id, listener_id, album_id, musical_entity_id, artist_id, non_admin_user_id**} -> **задоволува БКНФ** |
| | 265 | |
| | 266 | |
| | 267 | |
| | 268 | == Проверка за 4НФ |
| | 269 | |
| | 270 | Релацијата R7 **не ја задоволува 4НФ** бидејќи содржи мултивредносни зависности, како на пример `listener_id →→ song_id, timestamp`, што значи дека слушањата на песните се целосно независни од лајковите на песните. |
| | 271 | |
| | 272 | == Декомпозиција по 4Нф: |
| | 273 | |
| | 274 | - **Playlist_Songs (song_id, playlist_id)** |
| | 275 | - **Performs_At (event_id, artist_id)** |
| | 276 | - **Likes (listener_id, musical_entity_id) |
| | 277 | - **Follows (follower_id, followee_id)**- во оваа релација `follower_id` и `followee_id` се всушност сложен примарен клуч и двете од нив се надворешни клучеви во релацијата `Non_Admin_Users`. |
| | 278 | - **Saved_Playlists (listener_id, playlist_id)** |
| | 279 | - **Listens (listener_id, song_id, timestamp)** |
| | 280 | |
| | 281 | Lossless join: Доколку направиме join по заедничките атрибути на овие релации можеме |
| | 282 | да ја реконстроуираме R7. |
| | 283 | |
| | 284 | Dependency preservation: Новодобиените релации не претставуваат функционални зависности. |
| | 285 | |
| | 286 | |
| | 287 | Финални релации: |
| | 288 | |
| | 289 | 1. Playlists(**playlist_id**, playlist_name, playlist_cover, listener_id) |
| | 290 | 2. Songs(**song_id**, link, album_id) |
| | 291 | 3. Events(**event_id**, event_name, location, venue, date, time, user_id) |
| | 292 | 4. Admins(**admin_id**) |
| | 293 | 5. Listeners(**listener_id**) |
| | 294 | 6. Non_Admin_Users(**non_admin_user_id**) |
| | 295 | 7. Users(**user_id**, profile_photo, email, username, full_name, password) |
| | 296 | 8. Albums(**album_id**) |
| | 297 | 9. Musical_Entities(**musical_entity_id**, title, genre, me_cover, release_date, artist_id) |
| | 298 | 10. Artist_Contributions(**artist_id, musical_entity_id**, role) |
| | 299 | 11. Reviews(**listener_id, musical_entity_id**, grade, comment) |
| | 300 | 12. Artists(**artist_id**) |
| | 301 | 13. Playlist_Songs(**song_id, playlist_id**) |
| | 302 | 14. Performs_At (**event_id, artist_id**) |
| | 303 | 15. Likes(**listener_id, musical_entity_id**) |
| | 304 | 16. Follows(**follower_id, followee_id**) |
| | 305 | 17. Saved_Playlists (**listener_id, playlist_id**) |
| | 306 | 18. Listens (**listener_id, song_id, timestamp**) |
| | 307 | |