| 37 | | FD2: component_id -> component_name, brand, component_price, component_type, img_url |
| 38 | | |
| 39 | | FD3: component_id(cpu) -> cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp |
| 40 | | |
| 41 | | FD4: component_id(gpu) -> gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length |
| 42 | | |
| 43 | | FD5: component_id(memory) -> memory_type, memory_speed, memory_capacity, memory_modules |
| 44 | | |
| 45 | | FD6: component_id(storage) -> storage_type, storage_capacity, storage_form_factor |
| 46 | | |
| 47 | | FD7: component_id (power_supply) -> power_supply_type, power_supply_capacity, power_supply_form_factor |
| 48 | | |
| 49 | | FD8: component_id(motherboard) -> motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots |
| 50 | | |
| 51 | | FD9: component_id(pc_case) -> pc_case_cooler_max_height, pc_case_gpu_max_length |
| 52 | | |
| 53 | | FD10: component_id(cooler) -> cooler_type, cooler_height, cooler_max_tdp_supported |
| 54 | | |
| 55 | | FD11: component_id(memory_card) -> memory_card_num_slots, memory_card_interface |
| 56 | | |
| 57 | | FD12: component_id(optical_drive) -> optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed |
| 58 | | |
| 59 | | FD13: component_id(sound_card) -> sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel |
| 60 | | |
| 61 | | FD14: component_id(cables) -> cables_length_cm, cables_type |
| 62 | | |
| 63 | | FD15: component_id(network_adapter) -> network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas |
| 64 | | |
| 65 | | FD16: component_id(network_card) -> network_card_num_ports, network_card_speed, network_card_interface |
| 66 | | |
| 67 | | FD17: build_id -> user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved |
| 68 | | |
| 69 | | FD18: build_id, component_id -> num_components |
| 70 | | |
| 71 | | FD19: build_id, user_id -> / |
| | 40 | FD2: admin_user_id -> user_id (FK relationship) |
| | 41 | |
| | 42 | FD3: component_id -> component_name, component_brand, component_price, component_type, component_img_url |
| | 43 | |
| | 44 | FD4: component_id(cpu) -> cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp |
| | 45 | |
| | 46 | FD5: component_id(gpu) -> gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length |
| | 47 | |
| | 48 | FD6: component_id(memory) -> memory_type, memory_speed, memory_capacity, memory_modules |
| | 49 | |
| | 50 | FD7: component_id(storage) -> storage_type, storage_capacity, storage_form_factor |
| | 51 | |
| | 52 | FD8: component_id(power_supply) -> power_supply_type, power_supply_wattage, power_supply_form_factor |
| | 53 | |
| | 54 | FD9: component_id(motherboard) -> motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots |
| | 55 | |
| | 56 | FD10: component_id(pc_case) -> pc_case_cooler_max_height, pc_case_gpu_max_length |
| | 57 | |
| | 58 | FD11: component_id(cooler) -> cooler_type, cooler_height, cooler_max_tdp_supported |
| | 59 | |
| | 60 | FD12: component_id(memory_card) -> memory_card_num_slots, memory_card_interface |
| | 61 | |
| | 62 | FD13: component_id(optical_drive) -> optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed |
| | 63 | |
| | 64 | FD14: component_id(sound_card) -> sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel |
| | 65 | |
| | 66 | FD15: component_id(cables) -> cables_length_cm, cables_type |
| | 67 | |
| | 68 | FD16: component_id(network_adapter) -> network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas |
| | 69 | |
| | 70 | FD17: component_id(network_card) -> network_card_num_ports, network_card_speed, network_card_interface |
| | 71 | |
| | 72 | FD18: build_id -> build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved |
| | 73 | |
| | 74 | FD19: build_id, component_id -> build_component_num_components |
| 84 | | username, password, email, component_name, brand, component_price, component_type, img_url, cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp, gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length, memory_type, memory_speed, memory_capacity, memory_modules, storage_type, storage_capacity, storage_form_factor, power_supply_type, power_supply_capacity, power_supply_form_factor, motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots, pc_case_cooler_max_height, pc_case_gpu_max_length, num_slots, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket, cooler_type, cooler_height, cooler_max_tdp_supported, memory_card_num_slots, memory_card_interface, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel, cables_length_cm, cables_type, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas, network_card_num_ports, network_card_speed, network_card_interface, build_name, build_created_at, build_description, build_total_price, build_is_approved, rating_build_value, review_content, review_created_at, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type |
| 85 | | |
| 86 | | Attributes that never appear on the right side(only left) are component_id, review_id, suggestion_id. This means that they must be in every candidate key because nothing can determine them. |
| 87 | | |
| 88 | | Lets test the minimal candidate key K = { component_id, review_id, suggestion_id } |
| | 91 | username, password, email, component_name, component_brand, component_price, component_type, component_img_url, cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp, gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length, memory_type, memory_speed, memory_capacity, memory_modules, storage_type, storage_capacity, storage_form_factor, power_supply_type, power_supply_wattage, power_supply_form_factor, motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots, pc_case_cooler_max_height, pc_case_gpu_max_length, case_storage_num_slots, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_type, cooler_height, cooler_max_tdp_supported, cooler_cpu_socket, memory_card_num_slots, memory_card_interface, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel, cables_length_cm, cables_type, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas, network_card_num_ports, network_card_speed, network_card_interface, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved, build_component_num_components, rating_build_value, review_build_id, review_user_id, review_content, review_created_at, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type |
| | 92 | |
| | 93 | Attributes that never appear on the right side (only left) are user_id, admin_user_id, component_id, build_id, review_id, suggestion_id. This means that they must be in every candidate key because nothing can determine them. |
| | 94 | |
| | 95 | Let's compute the closures of each individual left-side attribute to see what we can derive from each: |
| | 96 | |
| | 97 | {user_id}+ : By applying FD1 we add username, password, email. So {user_id}+ = {user_id, username, password, email}. This is NOT a superkey (missing all other attributes). |
| | 98 | |
| | 99 | {admin_user_id}+ : By applying FD2, admin_user_id → user_id. By applying FD1, user_id → username, password, email. So {admin_user_id}+ = {admin_user_id, user_id, username, password, email}. This is NOT a superkey (missing component_id, build_id, review_id, suggestion_id and their dependents). |
| | 100 | |
| | 101 | {component_id}+ : By applying FD3-FD17 we add component_name, component_brand, component_price, component_type, component_img_url, cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp, gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length, memory_type, memory_speed, memory_capacity, memory_modules, storage_type, storage_capacity, storage_form_factor, power_supply_type, power_supply_wattage, power_supply_form_factor, motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots, pc_case_cooler_max_height, pc_case_gpu_max_length, cooler_type, cooler_height, cooler_max_tdp_supported, memory_card_num_slots, memory_card_interface, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel, cables_length_cm, cables_type, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas, network_card_num_ports, network_card_speed, network_card_interface. So {component_id}+ contains all component attributes but is NOT a superkey (missing user_id, admin_user_id, build_id, review_id, suggestion_id and their dependents). |
| | 102 | |
| | 103 | {build_id}+ : By applying FD18 we add build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved. By applying FD19 we need component_id which we don't have. By applying FD20 and FD21 we need user_id which we don't have. So {build_id}+ = {build_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved}. This is NOT a superkey. |
| | 104 | |
| | 105 | {review_id}+ : By applying FD22 we add review_build_id, review_user_id, review_content, review_created_at. We cannot derive build_id or user_id directly from the relation. So {review_id}+ = {review_id, review_build_id, review_user_id, review_content, review_created_at}. This is NOT a superkey. |
| | 106 | |
| | 107 | {suggestion_id}+ : By applying FD24 we add suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type. We cannot derive admin_user_id directly. So {suggestion_id}+ = {suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type}. This is NOT a superkey. |
| | 108 | |
| | 109 | Since no single left-side attribute can determine all others, we must combine them. Let's test the candidate key K = {user_id, admin_user_id, component_id, review_id, suggestion_id, build_id}. |
| 111 | | By applying FD21, we add: |
| 112 | | build_id, user_id, review_content, review_created_at |
| 113 | | |
| 114 | | By applying FD17, we add: |
| 115 | | build_name, build_created_at, build_description, build_total_price, build_is_approved |
| 116 | | |
| 117 | | By applying FD1, we add: |
| 118 | | username, password, email |
| 119 | | |
| 120 | | By applying FD22, we add: |
| 121 | | suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type |
| 122 | | |
| 123 | | By applying FD18 and FD20, we add: |
| 124 | | num_components, rating_build_value |
| 125 | | |
| 126 | | If we remove the component_id - then the component attributes cant be determined. Same thing goes for review_id and suggestion_id. |
| 127 | | After excluding multivalued attributes which we handle separatelu in 1NF, K+ contains all attributes of R, which means that K is a superkey. |
| | 137 | By applying FD18, we add: |
| | 138 | build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved |
| | 139 | |
| | 140 | By applying FD19 (we have build_id and component_id), we add: |
| | 141 | build_component_num_components |
| | 142 | |
| | 143 | By applying FD20 and FD21 (we have build_id and user_id), we add: |
| | 144 | rating_build_value |
| | 145 | |
| | 146 | By applying FD22, we add: |
| | 147 | review_build_id, review_user_id, review_content, review_created_at |
| | 148 | |
| | 149 | By applying FD24, we add: |
| | 150 | suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type |
| | 151 | |
| | 152 | After excluding multivalued attributes which we handle separately in 1NF, K+ contains all attributes of R, which means that K is a superkey. |
| | 153 | |
| | 154 | To verify that K = {user_id, admin_user_id, component_id, review_id, suggestion_id, build_id} is a candidate key, we test all proper subsets: |
| | 155 | |
| | 156 | {admin_user_id, component_id, review_id, suggestion_id, build_id}+ is missing user_id which blocks FD20 and FD21 (need user_id for build_id, user_id -> rating_build_value and favorite_build). |
| | 157 | |
| | 158 | {user_id, component_id, review_id, suggestion_id, build_id}+ is missing admin_user_id which blocks FD24 completely (need to derive suggestion_admin_id from admin_user_id). |
| | 159 | |
| | 160 | {user_id, admin_user_id, review_id, suggestion_id, build_id}+ is missing component_id which blocks FD19 (need build_id, component_id for build_component_num_components) and all component attributes. |
| | 161 | |
| | 162 | {user_id, admin_user_id, component_id, suggestion_id, build_id}+ is missing review_id which blocks FD22 (need review_id -> review attributes). |
| | 163 | |
| | 164 | {user_id, admin_user_id, component_id, review_id, build_id}+ is missing suggestion_id which blocks FD24 (need suggestion_id -> suggestion attributes). |
| | 165 | |
| | 166 | {user_id, admin_user_id, component_id, review_id, suggestion_id}+ is missing build_id which blocks FD18, FD19, FD20, FD21 (need build_id -> build attributes and build_id for various composite FDs). |
| | 167 | |
| | 168 | Therefore, K = {user_id, admin_user_id, component_id, review_id, suggestion_id, build_id} is the minimal candidate key (no proper subset is a superkey). |
| 144 | | FD2-FD16: component_id is part of the key, but the these attributes such as component_name, brand, component_price etc. depend only on component_id. |
| 145 | | |
| 146 | | We will decompose by creating new relations from R following FD2 to FD16 where the attributes will depend only on component_id: |
| 147 | | |
| 148 | | component_id -> component_id, component_name, brand, component_price, component_type, img_url |
| | 186 | FD1: user_id is part of the key, but these attributes such as username, password, email depend only on user_id. |
| | 187 | |
| | 188 | FD2: admin_user_id is part of the key, but user_id depends only on admin_user_id. |
| | 189 | |
| | 190 | FD3-FD17: component_id is part of the key, but these attributes such as component_name, component_brand, component_price etc. depend only on component_id. |
| | 191 | |
| | 192 | FD18: build_id is part of the key, but these attributes such as build_user_id, build_name etc. depend only on build_id. |
| | 193 | |
| | 194 | FD19: (build_id, component_id) is part of the key, but build_component_num_components depends on (build_id, component_id). |
| | 195 | |
| | 196 | FD20: (build_id, user_id) is part of the key, but rating_build_value depends on (build_id, user_id). |
| | 197 | |
| | 198 | FD21: (build_id, user_id) is part of the key, but represents favorite_build (no attributes). |
| | 199 | |
| | 200 | FD22: review_id is part of the key, but these attributes such as review_build_id, review_user_id, review_content, review_created_at depend only on review_id. |
| | 201 | |
| | 202 | FD24: suggestion_id is part of the key, but these attributes such as suggestion_user_id, suggestion_admin_id etc. depend only on suggestion_id. |
| | 203 | |
| | 204 | We will decompose by creating new relations from R following FD1, FD2 to FD24 where the attributes will depend only on the determinant attribute(s), which will become the primary key: |
| | 205 | |
| | 206 | user_id -> username, password, email |
| | 207 | |
| | 208 | admin_user_id -> user_id |
| | 209 | |
| | 210 | component_id -> component_name, component_brand, component_price, component_type, component_img_url |
| 165 | | component_id -> cooler_type, cooler_height, cooler_max_tdp_supported, cooler_cpu_socket |
| 166 | | |
| 167 | | component_id -> memory_card_num_slots, memory_card_interface |
| 168 | | |
| 169 | | component_id -> optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed |
| 170 | | |
| 171 | | component_id -> sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel |
| 172 | | |
| 173 | | component_id -> cables_length_cm, cables_type |
| 174 | | |
| 175 | | component_id -> network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas |
| 176 | | |
| 177 | | component_id -> network_card_num_ports, network_card_speed, network_card_interface |
| 178 | | |
| 179 | | Primary key in all of these is component_id. |
| 180 | | |
| 181 | | FD21: review_id is part of the key, but these attributes build_id, user_id, review_content, review_created_at depend only on review_id. |
| 182 | | |
| 183 | | We will solve this partial dependency by creating a new relation: |
| 184 | | |
| 185 | | review_id -> build_id, user_id, review_content, review_created_at |
| 186 | | |
| 187 | | Primary key here is review_id. |
| 188 | | |
| 189 | | FD22: suggestion_id is part of the key, but user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type depend only on suggestion_id. |
| 190 | | |
| 191 | | We will solve this partial dependency by creating a new relation: |
| 192 | | |
| 193 | | suggestion_id -> user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type |
| 194 | | |
| 195 | | We get the following relations: |
| 196 | | |
| 197 | | R1 { review_id, build_id, user_id, review_content, review_created_at } where PK = review_id - BCNF |
| 198 | | |
| 199 | | R2 { suggestion_id, user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type } where PK = suggestion_id - BCNF |
| 200 | | |
| 201 | | R3 { component_id, component_name, brand, component_price, component_type, img_url } where PK = component_id - BCNF |
| | 226 | build_id -> build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved |
| | 227 | |
| | 228 | build_id, component_id -> build_component_num_components |
| | 229 | |
| | 230 | build_id, user_id -> rating_build_value |
| | 231 | |
| | 232 | build_id, user_id -> (represents favorite_build) |
| | 233 | |
| | 234 | review_id -> review_build_id, review_user_id, review_content, review_created_at |
| | 235 | |
| | 236 | suggestion_id -> suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type |
| | 237 | |
| | 238 | Primary key in all of these is the attribute(s) on the left side. |
| | 239 | |
| | 240 | == 2NF Decomposition |
| | 241 | |
| | 242 | All these partial dependencies are addressed in 2NF. We will solve these partial dependencies by creating new relations where each determinant becomes a primary key: |
| | 243 | |
| | 244 | R1 { user_id, username, password, email } where PK = user_id - BCNF |
| | 245 | |
| | 246 | R2 { admin_user_id, user_id } where PK = admin_user_id, FK = user_id -> R1.user_id - BCNF |
| | 247 | |
| | 248 | R3 { component_id, component_name, component_brand, component_price, component_type, component_img_url } where PK = component_id - BCNF |
| 215 | | R10 { component_id, pc_case_cooler_max_height, pc_case_gpu_max_length } where PK = component_id - BCNF |
| 216 | | |
| 217 | | R11 { component_id, cooler_type, cooler_height, cooler_max_tdp_supported } where PK = component_id - BCNF |
| 218 | | |
| 219 | | R12 { component_id, memory_card_num_slots, memory_card_interface } where PK = component_id - BCNF |
| 220 | | |
| 221 | | R13 { component_id, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed } where PK = component_id - BCNF |
| 222 | | |
| 223 | | R14 { component_id, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel } where PK = component_id - BCNF |
| 224 | | |
| 225 | | R15 { component_id, cables_length_cm, cables_type } where PK = component_id - BCNF |
| 226 | | |
| 227 | | R16 { component_id, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas } where PK = component_id - BCNF |
| 228 | | |
| 229 | | R17 { component_id, network_card_num_ports, network_card_speed, network_card_interface } where PK = component_id - BCNF |
| 230 | | |
| 231 | | R18 { component_id, pc_case_storage_form_factor , num_slots } where PK = component_id and pc_case_storage_form_factor - BCNF |
| 232 | | |
| 233 | | R19 { component_id, pc_case_ps_form_factor } where PK = component_id and pc_case_ps_form_factor - BCNF |
| 234 | | |
| 235 | | R20 { component_id, pc_case_mobo_form_factor } where PK = component_id and pc_case_mobo_form_factor - BCNF |
| 236 | | |
| 237 | | R21 { component_id, cooler_cpu_socket } where PK = component_id and cooler_cpu_socket - BCNF |
| 238 | | |
| 239 | | The remainder of R { component_id, review_id, suggestion_id, build_id, user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved, num_components, rating_build_value, username, password, email } where PK = K (component_id, review_id, suggestion_id) |
| 240 | | |
| 241 | | 2NF is satisfied but the remaining of R has transitive dependencies which violate 3NF. When looking at FD17: build_id -> build_name, build_created_at, build_description, build_total_price, build_is_approved, here build_id is not part of the candidate key K, but it determines build_name and other attributes. The same thing goes for user_id -> username, password, email when looking at FD1. We will handle these transitive dependencies by creating separate tables. |
| 242 | | |
| 243 | | == 3NF decomposition |
| 244 | | R22 { user_id, username, password, email } where PK = user_id - BCNF |
| 245 | | |
| 246 | | R23 { build_id, user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved } where PK = build_id – BCNF |
| 247 | | |
| 248 | | Leftover relation R { component_id, review_id, suggestion_id, build_id, user_id, num_components, rating_build_value } |
| 249 | | |
| 250 | | From FD18 (build_id, component_id) → num_components we see that build_id and component_id is not a superkey of leftover relation R, this violates BCNF. Same thing goes for FD19 (build_id, user_id) -> / and FD20 (build_id, user_id) → rating_build_value, build_id and user_id is not a superkey of the leftover relation. We will decompose by creating new relations |
| 251 | | |
| 252 | | R24 { build_id , component_id, num_components } where PK = build_id, component_id - BCNF |
| 253 | | |
| 254 | | R25 { build_id, user_id, rating_build_value } where PK = build_id, user_id - BCNF |
| 255 | | |
| 256 | | R26 { build_id, user_id } where PK = build_id, user_id – BCNF |
| | 262 | R10 { component_id, pc_case_cooler_max_height, pc_case_gpu_max_length } where PK = component_id - BCNF |
| | 263 | |
| | 264 | R11 { build_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved } where PK = build_id - BCNF |
| | 265 | |
| | 266 | R12 { build_id, component_id, build_component_num_components } where PK = (build_id, component_id) - BCNF |
| | 267 | |
| | 268 | R13 { build_id, user_id, rating_build_value } where PK = (build_id, user_id) - BCNF |
| | 269 | |
| | 270 | R14 { build_id, user_id } where PK = (build_id, user_id) - BCNF |
| | 271 | |
| | 272 | R15 { component_id, cooler_type, cooler_height, cooler_max_tdp_supported } where PK = component_id - BCNF |
| | 273 | |
| | 274 | R16 { component_id, memory_card_num_slots, memory_card_interface } where PK = component_id - BCNF |
| | 275 | |
| | 276 | R17 { component_id, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed } where PK = component_id - BCNF |
| | 277 | |
| | 278 | R18 { component_id, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel } where PK = component_id - BCNF |
| | 279 | |
| | 280 | R19 { component_id, cables_length_cm, cables_type } where PK = component_id - BCNF |
| | 281 | |
| | 282 | R20 { component_id, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas } where PK = component_id - BCNF |
| | 283 | |
| | 284 | R21 { component_id, network_card_num_ports, network_card_speed, network_card_interface } where PK = component_id - BCNF |
| | 285 | |
| | 286 | R22 { review_id, review_build_id, review_user_id, review_content, review_created_at } where PK = review_id, Alt Key = (review_build_id, review_user_id) - BCNF |
| | 287 | |
| | 288 | R23 { suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type } where PK = suggestion_id - BCNF |
| | 289 | |
| | 290 | The remainder of R { component_id, review_id, suggestion_id, build_id, user_id, admin_user_id } where PK = K (component_id, review_id, suggestion_id, build_id, user_id, admin_user_id) |
| | 291 | |
| | 292 | 2NF is satisfied for all relations. All partial dependencies have been eliminated. No transitive dependencies can exist in relations with only key attributes or attributes derived entirely from the key. |
| | 293 | |
| | 294 | All relations are already in BCNF since every determinant of every functional dependency is a candidate key of its respective relation. |