| | 53 | Before we start the aim of a candidate key is to satisfy the following requirements: |
| | 54 | - The candidate key closure must be able to cover every attribute in the relation R. |
| | 55 | - And for the key to be minimal, we only keep ones that will be able to satisfy the above mentioned rule. |
| | 56 | |
| | 57 | The starting point would be finding every attributes that are never found on the right side in any of the functional dependencies. |
| | 58 | |
| | 59 | This means that these attributes don’t get determined by any other. So due to this we need to include them always in the candidate keys. |
| | 60 | |
| | 61 | {{{ |
| | 62 | architect_id — nothing in Fc produces it |
| | 63 | inquiry_id — nothing in Fc produces it |
| | 64 | appointment_id — appears on the RHS of FD17 (timeslot_id → appointment_id), |
| | 65 | but timeslot_id itself appears on the RHS of FD16 |
| | 66 | (appointment_id → timeslot_id), meaning the two mutually |
| | 67 | determine each other. Neither can be derived from anything |
| | 68 | outside that pair, so one of them must be in every key. |
| | 69 | }}} |
| | 70 | |
| | 71 | This gives us the base set to test: {architect_id, inquiry_id, appointment_id}. |
| | 72 | |
| | 73 | Testing the coverage of this candidate key results in the complete cover of all attributes in R |
| | 74 | {architect_id, inquiry_id, appointment_id} is a superkey. |
| | 75 | |
| | 76 | If we try to remove each to get a minimal candidate key the following happens: |
| | 77 | |
| | 78 | By removing architect_id we lose the ability to reach architect_name which is only reachable via FD03 and that requires an architect_id. |
| | 79 | |
| | 80 | By removing inquiry_id we lose the ability to reach inquiry_message, inquiry_status, inquiry_created_at which are only reachable via FD15. |
| | 81 | |
| | 82 | By removing appointment_id we lose the ability to reach multiple attributes (appt_status, timeslot_id, ts_date, ts_time_start, ts_time_end, ts_status). |
| | 83 | |
| | 84 | Another viable candidate key is {architect_id, inquiry_id, timeslot_id}: |
| | 85 | |
| | 86 | From the closure test above we know appointment_id is required to reach |
| | 87 | appt_status and the timeslot chain. However, appointment_id and timeslot_id |
| | 88 | mutually determine each other: |
| | 89 | |
| | 90 | {{{ |
| | 91 | FD16: appointment_id → timeslot_id |
| | 92 | FD17: timeslot_id → appointment_id |
| | 93 | }}} |
| | 94 | |
| | 95 | This means timeslot_id can substitute for appointment_id. Testing the closure |
| | 96 | of {architect_id, inquiry_id, timeslot_id} results in all attributes being covered. |
| | 97 | |
| | 98 | There arent any other substitutable attributes left, so that leaves us with the 2 candidate keys we tested. |
| | 99 | |