| 274 | | За секоја декомпозиција `R -> R1, R2`, `join`-от е lossless ако и само ако: |
| 275 | | `(R1 ∩ R2) -> R1` **ИЛИ** `(R1 ∩ R2) -> R2` |
| 276 | | |
| 277 | | Бидејќи декомпозицијата е вршена директно од глобалната релација `R` во посебни релации (не постепено `R->R1,R2->R3,R4...`), ја применуваме проверката за секој пар поврзани релации преку странски клуч: |
| 278 | | |
| 279 | | - `USERS` — `TRAINING_USERS`: Пресек `{user_id}` → `user_id` е `PK` во `USERS` → суперклуч ✓ |
| 280 | | - `USERS` — `FINANCE_USERS`: Пресек `{user_id}` → `user_id` е `PK` во `USERS` → суперклуч ✓ |
| 281 | | - `USERS` — `INVESTOR_USERS`: Пресек `{user_id}` → `user_id` е `PK` во `USERS` → суперклуч ✓ |
| 282 | | - `USERS` — `DISCIPLINE_USERS`: Пресек `{user_id}` → `user_id` е `PK` во `USERS` → суперклуч ✓ |
| 283 | | - `USERS` — `CUSTOM_TRACKING_CATEGORIES`: Пресек `{user_id}` → `user_id` е `PK` во `USERS` → суперклуч ✓ |
| 284 | | - `USERS` — `DAILY_COMPLETION`: Пресек `{user_id}` → `user_id` е `PK` во `USERS` → суперклуч ✓ |
| 285 | | - `TRAINING_USERS` — `TRAINING_SESSIONS`: Пресек `{training_user_id}` → `training_user_id` е `PK` во `TRAINING_USERS` → суперклуч ✓ |
| 286 | | - `INVESTOR_USERS` — `ASSETS`: Пресек `{investor_user_id}` → `investor_user_id` е `PK` во `INVESTOR_USERS` → суперклуч ✓ |
| 287 | | - `WEIGHT_USERS` — `DAILY_INTAKES`: Пресек `{weight_user_id}` → `weight_user_id` е `PK` во `WEIGHT_USERS` → суперклуч ✓ |
| 288 | | - `FINANCE_USERS` — `INCOMES`: Пресек `{finance_user_id}` → `finance_user_id` е `PK` во `FINANCE_USERS` → суперклуч ✓ |
| 289 | | - `DISCIPLINE_USERS` — `TASKS`: Пресек `{discipline_user_id}` → `discipline_user_id` е `PK` во `DISCIPLINE_USERS` → суперклуч ✓ |
| 290 | | - `CUSTOM_TRACKING_CATEGORIES` — `TASKS`: Пресек `{custom_tracking_id}` → `custom_tracking_id` е `PK` во `CUSTOM_TRACKING_CATEGORIES` → суперклуч ✓ |
| 291 | | - `TASKS` — `TASK_DAILY_COMPLETION`: Пресек `{task_id}` → `task_id` е `PK` во `TASKS` → суперклуч ✓ |
| 292 | | - `DAILY_COMPLETION` — `TASK_DAILY_COMPLETION`: Пресек `{daily_completion_id}` → `daily_completion_id` е `PK` во `DAILY_COMPLETION` → суперклуч ✓ |
| 293 | | |
| 294 | | **Заклучок:** Сите декомпозиции имаат **lossless join** својство. ✓ |
| | 274 | **Теоретска основа:** За секоја декомпозиција на релација R во R1 и R2, join-от е lossless ако и само ако (R1 ∩ R2) → R1 или (R1 ∩ R2) → R2, т.е. заедничките атрибути формираат суперклуч барем во една од двете нови релации. |
| | 275 | |
| | 276 | Бидејќи нашата декомпозиција се изведува чекор-по-чекор, за секој чекор посебно ја проверуваме оваа особина. |
| | 277 | |
| | 278 | --- |
| | 279 | |
| | 280 | **ЧЕКОР 1: Декомпозиција од глобална R во 1НФ** |
| | 281 | |
| | 282 | **Чекор 1.1: Издвојување на USERS** |
| | 283 | |
| | 284 | R(сите атрибути) → USERS(user_id, email, username, password) + R1(останати атрибути) |
| | 285 | |
| | 286 | Пресек: {user_id} |
| | 287 | |
| | 288 | Дали {user_id} → USERS? Да, user_id е примарен клуч во USERS. |
| | 289 | |
| | 290 | Условот (R1 ∩ R2) → R1 е задоволен → **Lossless join ✓** |
| | 291 | |
| | 292 | --- |
| | 293 | |
| | 294 | **Чекор 1.2: Издвојување на TRAINING_USERS** |
| | 295 | |
| | 296 | R1 → TRAINING_USERS(training_user_id, training_gender, training_age, training_weight) + R2(останати атрибути) |
| | 297 | |
| | 298 | Пресек: {training_user_id} |
| | 299 | |
| | 300 | Дали {training_user_id} → TRAINING_USERS? Да, training_user_id е примарен клуч во TRAINING_USERS. |
| | 301 | |
| | 302 | **Lossless join ✓** |
| | 303 | |
| | 304 | --- |
| | 305 | |
| | 306 | **Чекор 1.3: Издвојување на TRAINING_SESSIONS** |
| | 307 | |
| | 308 | R2 → TRAINING_SESSIONS(training_id, training_user_id, training_date, training_type, training_duration, training_calories) + R3(останати атрибути) |
| | 309 | |
| | 310 | Пресек: {training_id} |
| | 311 | |
| | 312 | Дали {training_id} → TRAINING_SESSIONS? Да, training_id е примарен клуч во TRAINING_SESSIONS. |
| | 313 | |
| | 314 | **Lossless join ✓** |
| | 315 | |
| | 316 | --- |
| | 317 | |
| | 318 | **Чекор 1.4: Издвојување на INVESTOR_USERS** |
| | 319 | |
| | 320 | R3 → INVESTOR_USERS(investor_user_id) + R4(останати атрибути) |
| | 321 | |
| | 322 | Пресек: {investor_user_id} |
| | 323 | |
| | 324 | Дали {investor_user_id} → INVESTOR_USERS? Да, investor_user_id е примарен клуч во INVESTOR_USERS. |
| | 325 | |
| | 326 | **Lossless join ✓** |
| | 327 | |
| | 328 | --- |
| | 329 | |
| | 330 | **Чекор 1.5: Издвојување на ASSETS** |
| | 331 | |
| | 332 | R4 → ASSETS(asset_id, investor_user_id, asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity) + R5(останати атрибути) |
| | 333 | |
| | 334 | Пресек: {asset_id} |
| | 335 | |
| | 336 | Дали {asset_id} → ASSETS? Да, asset_id е примарен клуч во ASSETS. |
| | 337 | |
| | 338 | **Lossless join ✓** |
| | 339 | |
| | 340 | --- |
| | 341 | |
| | 342 | **Чекор 1.6: Издвојување на WEIGHT_USERS** |
| | 343 | |
| | 344 | R5 → WEIGHT_USERS(weight_user_id, weight_current, weight_height, weight_goal_weight, weight_goal_calories) + R6(останати атрибути) |
| | 345 | |
| | 346 | Пресек: {weight_user_id} |
| | 347 | |
| | 348 | Дали {weight_user_id} → WEIGHT_USERS? Да, weight_user_id е примарен клуч во WEIGHT_USERS. |
| | 349 | |
| | 350 | **Lossless join ✓** |
| | 351 | |
| | 352 | --- |
| | 353 | |
| | 354 | **Чекор 1.7: Издвојување на DAILY_INTAKES** |
| | 355 | |
| | 356 | R6 → DAILY_INTAKES(daily_intake_id, weight_user_id, daily_intake_date, daily_intake_calories) + R7(останати атрибути) |
| | 357 | |
| | 358 | Пресек: {daily_intake_id} |
| | 359 | |
| | 360 | Дали {daily_intake_id} → DAILY_INTAKES? Да, daily_intake_id е примарен клуч во DAILY_INTAKES. |
| | 361 | |
| | 362 | **Lossless join ✓** |
| | 363 | |
| | 364 | --- |
| | 365 | |
| | 366 | **Чекор 1.8: Издвојување на DISCIPLINE_USERS** |
| | 367 | |
| | 368 | R7 → DISCIPLINE_USERS(discipline_user_id) + R8(останати атрибути) |
| | 369 | |
| | 370 | Пресек: {discipline_user_id} |
| | 371 | |
| | 372 | Дали {discipline_user_id} → DISCIPLINE_USERS? Да, discipline_user_id е примарен клуч во DISCIPLINE_USERS. |
| | 373 | |
| | 374 | **Lossless join ✓** |
| | 375 | |
| | 376 | --- |
| | 377 | |
| | 378 | **Чекор 1.9: Издвојување на CUSTOM_TRACKING_CATEGORIES** |
| | 379 | |
| | 380 | R8 → CUSTOM_TRACKING_CATEGORIES(custom_tracking_id, user_id, custom_tracking_name) + R9(останати атрибути) |
| | 381 | |
| | 382 | Пресек: {custom_tracking_id} |
| | 383 | |
| | 384 | Дали {custom_tracking_id} → CUSTOM_TRACKING_CATEGORIES? Да, custom_tracking_id е примарен клуч во CUSTOM_TRACKING_CATEGORIES. |
| | 385 | |
| | 386 | **Lossless join ✓** |
| | 387 | |
| | 388 | --- |
| | 389 | |
| | 390 | **Чекор 1.10: Издвојување на TASKS** |
| | 391 | |
| | 392 | R9 → TASKS(task_id, discipline_user_id, custom_tracking_id, task_name, task_is_finished) + R10(останати атрибути) |
| | 393 | |
| | 394 | Пресек: {task_id} |
| | 395 | |
| | 396 | Дали {task_id} → TASKS? Да, task_id е примарен клуч во TASKS. |
| | 397 | |
| | 398 | **Lossless join ✓** |
| | 399 | |
| | 400 | --- |
| | 401 | |
| | 402 | **Чекор 1.11: Издвојување на DAILY_COMPLETION** |
| | 403 | |
| | 404 | R10 → DAILY_COMPLETION(daily_completion_id, user_id, daily_completion_date, daily_completion_procent) + R11(останати атрибути) |
| | 405 | |
| | 406 | Пресек: {daily_completion_id} |
| | 407 | |
| | 408 | Дали {daily_completion_id} → DAILY_COMPLETION? Да, daily_completion_id е примарен клуч во DAILY_COMPLETION. |
| | 409 | |
| | 410 | **Lossless join ✓** |
| | 411 | |
| | 412 | --- |
| | 413 | |
| | 414 | **Чекор 1.12: Издвојување на TASK_DAILY_COMPLETION** |
| | 415 | |
| | 416 | R11 → TASK_DAILY_COMPLETION(task_id, daily_completion_id) + R12(останати атрибути) |
| | 417 | |
| | 418 | Пресек: {task_id, daily_completion_id} |
| | 419 | |
| | 420 | Ова е спојна релација без не-клучни атрибути. Бидејќи нема дополнителни атрибути кои би можеле да се изгубат, join-от е lossless. |
| | 421 | |
| | 422 | **Lossless join ✓** |
| | 423 | |
| | 424 | --- |
| | 425 | |
| | 426 | **Чекор 1.13: Издвојување на FINANCE_USERS** |
| | 427 | |
| | 428 | R12 → FINANCE_USERS(finance_user_id, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit) + R13(останати атрибути) |
| | 429 | |
| | 430 | Пресек: {finance_user_id} |
| | 431 | |
| | 432 | Дали {finance_user_id} → FINANCE_USERS? Да, finance_user_id е примарен клуч во FINANCE_USERS. |
| | 433 | |
| | 434 | **Lossless join ✓** |
| | 435 | |
| | 436 | --- |
| | 437 | |
| | 438 | **Чекор 1.14: Издвојување на INCOMES** |
| | 439 | |
| | 440 | R13 → INCOMES(income_id, finance_user_id, income_date, income_amount) + R14(празна) |
| | 441 | |
| | 442 | Пресек: {income_id} |
| | 443 | |
| | 444 | Дали {income_id} → INCOMES? Да, income_id е примарен клуч во INCOMES. |
| | 445 | |
| | 446 | **Lossless join ✓** |
| | 447 | |
| | 448 | --- |
| | 449 | |
| | 450 | **ЗАКЛУЧОК:** Сите 14 чекори на декомпозиција го задоволуваат условот за lossless join. Конечниот модел овозможува целосна реконструкција на оригиналната релација R без губење или создавање на лажни податоци. |
| | 451 | |