wiki:Normalization

Version 19 (modified by 233144, 4 days ago) ( diff )

--

Normalization

1. Definition of the Universal Relation

We start from a single universal relation containing all attributes from the domain.

Universal_Relation( user_id, username, password, email, admin_user_id, component_id, 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, pc_case_storage_form_factor, pc_case_storage_num_slots, 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_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved, build_component_num_components, rating_build_value, review_id, review_build_id, review_user_id, review_content, review_created_at, suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type )

2. Functional Dependencies

We identify all functional dependencies that hold in the universal relation:

F = {

FD1: user_id → username, password, email

FD2: admin_user_id → ∅

FD3: component_id → component_name, component_brand, component_price, component_type, component_img_url

FD4: component_id → cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp

FD5: component_id → gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length

FD6: component_id → memory_type, memory_speed, memory_capacity, memory_modules

FD7: component_id → storage_type, storage_capacity, storage_form_factor

FD8: component_id → power_supply_type, power_supply_wattage, power_supply_form_factor

FD9: component_id → motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots

FD10: component_id → pc_case_cooler_max_height, pc_case_gpu_max_length

FD11: component_id → cooler_type, cooler_height, cooler_max_tdp_supported

FD12: component_id → memory_card_num_slots, memory_card_interface

FD13: component_id → optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed

FD14: component_id → sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel

FD15: component_id → cables_length_cm, cables_type

FD16: component_id → network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas

FD17: component_id → network_card_num_ports, network_card_speed, network_card_interface

FD18: build_id → build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved

FD19: (build_id, component_id) → build_component_num_components

FD20: (build_id, user_id) → rating_build_value

FD21: (build_id, user_id) → ∅ (represents favorite_build relationship)

FD22: review_id → review_build_id, review_user_id, review_content, review_created_at

FD23: suggestion_id → suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type

FD24: (component_id, pc_case_storage_form_factor) → pc_case_storage_num_slots

FD25: (component_id, pc_case_mobo_form_factor) → ∅

FD26: (component_id, pc_case_ps_form_factor) → ∅

FD27: (component_id, cooler_cpu_socket) → ∅

}

3. Candidate Keys and Primary Key

3.1 Determination of Candidate Keys

To find a candidate key, we must find a minimal set of attributes whose closure contains all attributes of the relation.

3.2 Attribute Classification (Left / Right Side)

Attribute Left Side Right Side Classification
user_id ✓ (FD1) Left only
username ✓ (FD1) Right only
password ✓ (FD1) Right only
email ✓ (FD1) Right only
admin_user_id ✓ (FD2) Left only
component_id ✓ (FD3-FD17, FD24-FD27) Left only
component_name ✓ (FD3) Right only
component_brand ✓ (FD3) Right only
component_price ✓ (FD3) Right only
component_type ✓ (FD3) Right only
component_img_url ✓ (FD3) Right only
[CPU attributes] ✓ (FD4) Right only
[GPU attributes] ✓ (FD5) Right only
[Memory attributes] ✓ (FD6) Right only
[Storage attributes] ✓ (FD7) Right only
[Power Supply attributes] ✓ (FD8) Right only
[Motherboard attributes] ✓ (FD9) Right only
pc_case_cooler_max_height ✓ (FD10) Right only
pc_case_gpu_max_length ✓ (FD10) Right only
pc_case_storage_form_factor ✓ (FD24) Left only
pc_case_storage_num_slots ✓ (FD24) Right only
pc_case_ps_form_factor ✓ (FD26) Left only
pc_case_mobo_form_factor ✓ (FD25) Left only
cooler_type ✓ (FD11) Right only
cooler_height ✓ (FD11) Right only
cooler_max_tdp_supported ✓ (FD11) Right only
cooler_cpu_socket ✓ (FD27) Left only
[Memory Card attributes] ✓ (FD12) Right only
[Optical Drive attributes] ✓ (FD13) Right only
[Sound Card attributes] ✓ (FD14) Right only
[Cables attributes] ✓ (FD15) Right only
[Network Adapter attributes] ✓ (FD16) Right only
[Network Card attributes] ✓ (FD17) Right only
build_id ✓ (FD18-FD21) Left only
build_user_id ✓ (FD18) Right only
build_name ✓ (FD18) Right only
build_created_at ✓ (FD18) Right only
build_description ✓ (FD18) Right only
build_total_price ✓ (FD18) Right only
build_is_approved ✓ (FD18) Right only
build_component_num_components ✓ (FD19) Right only
rating_build_value ✓ (FD20) Right only
review_id ✓ (FD22) Left only
review_build_id ✓ (FD22) Right only
review_user_id ✓ (FD22) Right only
review_content ✓ (FD22) Right only
review_created_at ✓ (FD22) Right only
suggestion_id ✓ (FD23) Left only
suggestion_user_id ✓ (FD23) Right only
suggestion_admin_id ✓ (FD23) Right only
suggestion_link ✓ (FD23) Right only
suggestion_admin_comment ✓ (FD23) Right only
suggestion_description ✓ (FD23) Right only
suggestion_status ✓ (FD23) Right only
suggestion_component_type ✓ (FD23) Right only

3.3 Attributes That Appear ONLY on the Left Side

The following attributes appear only on the left side of functional dependencies and never on the right side:

  • user_id – must be part of every candidate key
  • component_id – must be part of every candidate key
  • build_id – must be part of every candidate key
  • review_id – must be part of every candidate key
  • suggestion_id – must be part of every candidate key
  • pc_case_storage_form_factor – must be part of every candidate key
  • pc_case_ps_form_factor – must be part of every candidate key
  • pc_case_mobo_form_factor – must be part of every candidate key
  • cooler_cpu_socket – must be part of every candidate key
  • admin_user_id – must be part of every candidate key

3.4 Closure Computation

Step 1: We start with {user_id, component_id, build_id, review_id, suggestion_id, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket, admin_user_id} and compute the closure:

{user_id, component_id, build_id, review_id, suggestion_id, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket, admin_user_id}⁺:

  • From FD1 (user_id → username, password, email): We obtain username, password, email
  • From FD2 (admin_user_id → ∅): No new attributes
  • From FD3–FD17 (component_id → ...): We obtain 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
  • From FD18 (build_id → ...): We obtain build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved
  • From FD19 ((build_id, component_id) → build_component_num_components): We obtain build_component_num_components (both build_id and component_id already in closure)
  • From FD20 ((build_id, user_id) → rating_build_value): We obtain rating_build_value (both build_id and user_id already in closure)
  • From FD21 ((build_id, user_id) → ∅): No new attributes
  • From FD22 (review_id → ...): We obtain review_build_id, review_user_id, review_content, review_created_at
  • From FD23 (suggestion_id → ...): We obtain suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type
  • From FD24 ((component_id, pc_case_storage_form_factor) → pc_case_storage_num_slots): We obtain pc_case_storage_num_slots (both attributes already in closure)
  • From FD25–FD27 (composite FDs with empty RHS): No new attributes

Closure = Universal_Relation ✓ (all attributes are present)

3.5 Minimality Check

Testing proper subsets of K = {user_id, component_id, build_id, review_id, suggestion_id, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket, admin_user_id}:

Subset Closure Equals Universal_Relation? Justification
K − {user_id} ✗ NO Cannot derive username, password, email (FD1 requires user_id)
K − {component_id} ✗ NO Cannot derive component attributes (FD3–FD17 require component_id)
K − {build_id} ✗ NO Cannot derive build attributes (FD18 requires build_id)
K − {review_id} ✗ NO Cannot derive review attributes (FD22 requires review_id)
K − {suggestion_id} ✗ NO Cannot derive suggestion attributes (FD23 requires suggestion_id)
K − {pc_case_storage_form_factor} ✗ NO FD24 requires pc_case_storage_form_factor
K − {pc_case_ps_form_factor} ✗ NO FD26 requires pc_case_ps_form_factor
K − {pc_case_mobo_form_factor} ✗ NO FD25 requires pc_case_mobo_form_factor
K − {cooler_cpu_socket} ✗ NO FD27 requires cooler_cpu_socket
K − {admin_user_id} ✗ NO admin_user_id is a left-only attribute and must be in every candidate key

Conclusion: K = {user_id, component_id, build_id, review_id, suggestion_id, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket, admin_user_id} is minimal and is the only candidate key.

3.6 Choice of Primary Key

Chosen Primary Key: {user_id, component_id, build_id, review_id, suggestion_id, pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket, admin_user_id}

Justification: This is the primary key (minimal candidate key) because only with these attributes can we derive all remaining attributes from the universal relation through the closure of functional dependencies.

---

4. 1NF Decomposition

4.1 1NF Violation Identification

The relation violates 1NF because the attributes pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, and cooler_cpu_socket represent multivalued attributes. Each component_id can have multiple values for each of these attributes.

4.2 1NF Decomposition

Relation R1: Case_Storage_Form_Factors

Case_Storage_Form_Factors(component_id, pc_case_storage_form_factor, pc_case_storage_num_slots) PK: (component_id, pc_case_storage_form_factor)

Attributes Included: component_id, pc_case_storage_form_factor, pc_case_storage_num_slots

Functional Dependency Enforced: FD24: (component_id, pc_case_storage_form_factor) → pc_case_storage_num_slots

Lossless Join Check:

  • This relation is decomposed directly from the universal relation by extracting the multivalued attribute group pc_case_storage_form_factor
  • The composite primary key (component_id, pc_case_storage_form_factor) uniquely identifies each tuple
  • When joined back with the main relation via component_id, no spurious tuples are introduced
  • The decomposition captures the exact relationship defined by FD24
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD24: (component_id, pc_case_storage_form_factor) → pc_case_storage_num_slots
    • Determinant: (component_id, pc_case_storage_form_factor)
    • Dependent: pc_case_storage_num_slots
    • All attributes of FD24 appear together in this relation ✓
  • The functional dependency is directly enforceable within this schema
  • Result: PRESERVED ✓

---

Relation R2: Case_Ps_Form_Factors

Case_Ps_Form_Factors(component_id, pc_case_ps_form_factor) PK: (component_id, pc_case_ps_form_factor)

Attributes Included: component_id, pc_case_ps_form_factor

Functional Dependency Enforced: FD26: (component_id, pc_case_ps_form_factor) → ∅

Lossless Join Check:

  • Decomposed directly from the multivalued attribute pc_case_ps_form_factor
  • The primary key (component_id, pc_case_ps_form_factor) uniquely identifies the relationship
  • Joining with the main relation on component_id preserves all original tuples
  • No information loss occurs during decomposition or reconstruction
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD26: (component_id, pc_case_ps_form_factor) → ∅
    • This is a relationship-only functional dependency with empty RHS
    • The determinant (component_id, pc_case_ps_form_factor) is present as the primary key
    • All attributes involved in FD26 are contained in this relation ✓
  • Result: PRESERVED ✓

---

Relation R3: Case_Mobo_Form_Factors

Case_Mobo_Form_Factors(component_id, pc_case_mobo_form_factor) PK: (component_id, pc_case_mobo_form_factor)

Attributes Included: component_id, pc_case_mobo_form_factor

Functional Dependency Enforced: FD25: (component_id, pc_case_mobo_form_factor) → ∅

Lossless Join Check:

  • Decomposed from the multivalued attribute pc_case_mobo_form_factor
  • The composite key fully represents the relationship between component and motherboard form factor
  • Natural join on component_id with the main relation produces no spurious tuples
  • Complete reconstruction of the original relationship is possible
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD25: (component_id, pc_case_mobo_form_factor) → ∅
    • The relationship-only FD is preserved through the composite primary key
    • All attributes of FD25 present in this schema ✓
  • Result: PRESERVED ✓

---

Relation R4: Cooler_Cpu_Sockets

Cooler_Cpu_Sockets(component_id, cooler_cpu_socket) PK: (component_id, cooler_cpu_socket)

Attributes Included: component_id, cooler_cpu_socket

Functional Dependency Enforced: FD27: (component_id, cooler_cpu_socket) → ∅

Lossless Join Check:

  • Decomposed directly from the multivalued attribute cooler_cpu_socket
  • The primary key captures the complete relationship
  • Rejoining via component_id preserves all original tuples without duplication
  • No information loss in decomposition or reconstruction
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD27: (component_id, cooler_cpu_socket) → ∅
    • The relationship-only FD is preserved by the composite key structure
    • All attributes involved in FD27 are present ✓
  • Result: PRESERVED ✓

---

Relation R5: Universal_Relation_1NF

Universal_Relation_1NF(

user_id, username, password, email, admin_user_id, component_id, 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, build_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved, build_component_num_components, rating_build_value, review_id, review_build_id, review_user_id, review_content, review_created_at, suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type

) PK: (user_id, component_id, build_id, review_id, suggestion_id, admin_user_id)

Attributes Included: All original attributes except the multivalued ones (pc_case_storage_form_factor, pc_case_ps_form_factor, pc_case_mobo_form_factor, cooler_cpu_socket)

Functional Dependencies Enforced: FD1–FD23 (all except FD24–FD27)

Lossless Join Check:

  • The four decomposed multivalued relations can be joined back to this relation via component_id
  • Each tuple in this main relation corresponds to a set of tuples in each multivalued relation
  • The natural join R5 ⋈ R1 ⋈ R2 ⋈ R3 ⋈ R4 reconstructs the original universal relation without spurious tuples
  • All join paths are on component_id, a common attribute present in all relations
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD1: user_id → username, password, email — All attributes present ✓
  • FD2: admin_user_id → ∅ — Determinant present ✓
  • FD3–FD23: component_id or composite keys → dependent attributes — All attributes present ✓
  • All functional dependencies relevant to this relation are preserved
  • Result: PRESERVED ✓

---

5. 2NF Decomposition

5.1 2NF Violation Analysis

The Universal_Relation_1NF (R5) violates 2NF due to partial dependencies.

Primary Key: (user_id, component_id, build_id, review_id, suggestion_id, admin_user_id)

A partial dependency exists when a non-key attribute depends on only a proper subset of the composite primary key rather than the entire key.

Identified Partial Dependencies:

FD Determinant Proper Subset? Non-key Attributes Dependent 2NF Violation?
FD1 user_id ✓ YES username, password, email ✓ YES
FD2 admin_user_id ✓ YES (specialization) ✓ YES
FD3–FD17 component_id ✓ YES component attributes ✓ YES
FD18 build_id ✓ YES build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved ✓ YES
FD22 review_id ✓ YES review_build_id, review_user_id, review_content, review_created_at ✓ YES
FD23 suggestion_id ✓ YES suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type ✓ YES
FD19 (build_id, component_id) ✓ YES build_component_num_components ✓ YES
FD20 (build_id, user_id) ✓ YES rating_build_value ✓ YES
FD21 (build_id, user_id) ✓ YES (relationship only) ✓ YES

5.2 2NF Decomposition

We eliminate partial dependencies by creating new relations where each partial dependency determinant becomes a primary key.

---

2NF Relation 1: Users

Users(user_id, username, password, email) PK: user_id

Derived From: FD1 (user_id → username, password, email)

Functional Dependency Enforced: FD1

Lossless Join Check:

  • Before decomposition, user_id was part of the composite key in Universal_Relation_1NF
  • Now user_id becomes the sole primary key in Users
  • Intersection of Users and Universal_Relation_1NF: I = {user_id}
  • FD1 guarantees: user_id → username, password, email
  • The join condition is on user_id, which is a candidate key for Users
  • Natural join Users ⋈ Universal_Relation_1NF on user_id produces no spurious tuples
  • All original tuples can be reconstructed: ✓
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD1: user_id → username, password, email
    • Determinant (user_id) and all dependent attributes (username, password, email) are present in Users ✓
    • The FD is directly enforceable within this relation
  • No other FD involves only user_id and its dependents in Universal_Relation_1NF
  • Result: PRESERVED ✓

---

2NF Relation 2: Admins

Admins(admin_user_id) PK: admin_user_id FK: admin_user_id → Users.user_id

Derived From: FD2 (admin_user_id → ∅)

Functional Dependency Enforced: FD2

Lossless Join Check:

  • admin_user_id was part of the composite key in Universal_Relation_1NF
  • Now admin_user_id becomes the sole primary key in Admins
  • Intersection: I = {admin_user_id}
  • FD2 is a relationship-only dependency with empty dependent set
  • The join Admins ⋈ Universal_Relation_1NF on admin_user_id reconstructs the relationship
  • No spurious tuples introduced
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD2: admin_user_id → ∅
    • The determinant (admin_user_id) is the primary key ✓
    • This relationship-only FD is preserved through the key structure
  • Result: PRESERVED ✓

---

2NF Relation 3: Components

Components(component_id, component_name, component_brand, component_price, component_type, component_img_url) PK: component_id

Derived From: FD3 (component_id → component_name, component_brand, component_price, component_type, component_img_url)

Functional Dependency Enforced: FD3

Lossless Join Check:

  • component_id was part of the composite key in Universal_Relation_1NF
  • Now component_id becomes the sole primary key in Components
  • Intersection: I = {component_id}
  • FD3 guarantees: component_id uniquely determines all dependent attributes
  • Join Components ⋈ Universal_Relation_1NF on component_id is lossless
  • No spurious tuples introduced
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD3: component_id → component_name, component_brand, component_price, component_type, component_img_url
    • All attributes of FD3 present in Components ✓
    • The FD is directly enforceable within this relation
  • Result: PRESERVED ✓

---

2NF Relation 4: Cpu

Cpu(component_id, cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp) PK: component_id FK: component_id → Components.component_id

Derived From: FD4 (component_id → cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp)

Functional Dependency Enforced: FD4

Lossless Join Check:

  • component_id is a proper subset of the original composite key
  • component_id becomes the primary key in Cpu
  • Intersection: I = {component_id}
  • FD4 ensures all non-key attributes are uniquely determined by component_id
  • Join with Universal_Relation_1NF on component_id is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD4: component_id → cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp
    • All attributes present in Cpu ✓
    • Directly enforceable
  • Result: PRESERVED ✓

---

2NF Relation 5: Gpu

Gpu(component_id, gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length) PK: component_id FK: component_id → Components.component_id

Derived From: FD5

Lossless Join Check: LOSSLESS ✓ (same reasoning as Cpu)

Dependency Preservation Check: FD5 directly enforceable ✓ PRESERVED ✓

---

2NF Relation 6: Memory

Memory(component_id, memory_type, memory_speed, memory_capacity, memory_modules) PK: component_id FK: component_id → Components.component_id

Derived From: FD6

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 7: Storage

Storage(component_id, storage_type, storage_capacity, storage_form_factor) PK: component_id FK: component_id → Components.component_id

Derived From: FD7

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 8: Power_Supply

Power_Supply(component_id, power_supply_type, power_supply_wattage, power_supply_form_factor) PK: component_id FK: component_id → Components.component_id

Derived From: FD8

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 9: Motherboard

Motherboard(component_id, motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots) PK: component_id FK: component_id → Components.component_id

Derived From: FD9

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 10: Pc_Case

Pc_Case(component_id, pc_case_cooler_max_height, pc_case_gpu_max_length) PK: component_id FK: component_id → Components.component_id

Derived From: FD10

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 11: Cooler

Cooler(component_id, cooler_type, cooler_height, cooler_max_tdp_supported) PK: component_id FK: component_id → Components.component_id

Derived From: FD11

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 12: Memory_Card

Memory_Card(component_id, memory_card_num_slots, memory_card_interface) PK: component_id FK: component_id → Components.component_id

Derived From: FD12

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 13: Optical_Drive

Optical_Drive(component_id, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed) PK: component_id FK: component_id → Components.component_id

Derived From: FD13

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 14: Sound_Card

Sound_Card(component_id, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel) PK: component_id FK: component_id → Components.component_id

Derived From: FD14

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 15: Cables

Cables(component_id, cables_length_cm, cables_type) PK: component_id FK: component_id → Components.component_id

Derived From: FD15

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 16: Network_Adapter

Network_Adapter(component_id, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas) PK: component_id FK: component_id → Components.component_id

Derived From: FD16

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 17: Network_Card

Network_Card(component_id, network_card_num_ports, network_card_speed, network_card_interface) PK: component_id FK: component_id → Components.component_id

Derived From: FD17

Lossless Join Check: LOSSLESS ✓

Dependency Preservation Check: PRESERVED ✓

---

2NF Relation 18: Build

Build(build_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved) PK: build_id FK: build_user_id → Users.user_id

Derived From: FD18 (build_id → build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved)

Functional Dependency Enforced: FD18

Lossless Join Check:

  • build_id was part of the composite key in Universal_Relation_1NF
  • Now build_id becomes the sole primary key in Build
  • Intersection: I = {build_id}
  • FD18 guarantees all non-key attributes are uniquely determined by build_id
  • Join Build ⋈ Universal_Relation_1NF on build_id is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD18: build_id → build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved
    • All attributes present in Build ✓
    • Directly enforceable
  • Result: PRESERVED ✓

---

2NF Relation 19: Build_Component

Build_Component(build_id, component_id, build_component_num_components) PK: (build_id, component_id) FK: build_id → Build.build_id FK: component_id → Components.component_id

Derived From: FD19 ((build_id, component_id) → build_component_num_components)

Functional Dependency Enforced: FD19

Lossless Join Check:

  • (build_id, component_id) is NOT a proper subset; it equals the original combination for this FD
  • The composite key becomes the primary key of Build_Component
  • Intersection: I = {build_id, component_id}
  • FD19 guarantees the composite key determines the non-key attribute
  • Join with Universal_Relation_1NF on (build_id, component_id) is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD19: (build_id, component_id) → build_component_num_components
    • All attributes present ✓
    • Directly enforceable
  • Result: PRESERVED ✓

---

2NF Relation 20: Rating_Build

Rating_Build(build_id, user_id, rating_build_value) PK: (build_id, user_id) FK: build_id → Build.build_id FK: user_id → Users.user_id

Derived From: FD20 ((build_id, user_id) → rating_build_value)

Functional Dependency Enforced: FD20

Lossless Join Check:

  • (build_id, user_id) is NOT a proper subset of the original composite key
  • The composite key becomes the primary key of Rating_Build
  • Intersection: I = {build_id, user_id}
  • FD20 guarantees the composite key determines the non-key attribute
  • Join with Universal_Relation_1NF on (build_id, user_id) is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD20: (build_id, user_id) → rating_build_value
    • All attributes present ✓
    • Directly enforceable
  • Result: PRESERVED ✓

---

2NF Relation 21: Favorite_Build

Favorite_Build(build_id, user_id) PK: (build_id, user_id) FK: build_id → Build.build_id FK: user_id → Users.user_id

Derived From: FD21 ((build_id, user_id) → ∅)

Functional Dependency Enforced: FD21

Lossless Join Check:

  • (build_id, user_id) forms the complete schema of Favorite_Build
  • Intersection: I = {build_id, user_id}
  • The composite key captures the entire relationship
  • Join with Universal_Relation_1NF on (build_id, user_id) is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD21: (build_id, user_id) → ∅
    • The relationship-only FD is preserved through the composite key structure ✓
    • Determinant present as primary key
  • Result: PRESERVED ✓

---

2NF Relation 22: Review

Review(review_id, review_build_id, review_user_id, review_content, review_created_at) PK: review_id Alt Key: (review_build_id, review_user_id) FK: review_build_id → Build.build_id FK: review_user_id → Users.user_id

Derived From: FD22 (review_id → review_build_id, review_user_id, review_content, review_created_at)

Functional Dependency Enforced: FD22

Lossless Join Check:

  • review_id was part of the composite key in Universal_Relation_1NF
  • Now review_id becomes the sole primary key in Review
  • Intersection: I = {review_id}
  • FD22 guarantees review_id uniquely determines all non-key attributes
  • Join with Universal_Relation_1NF on review_id is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD22: review_id → review_build_id, review_user_id, review_content, review_created_at
    • All attributes present in Review ✓
    • Directly enforceable
  • Result: PRESERVED ✓

---

2NF Relation 23: Suggestions

Suggestions(suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type) PK: suggestion_id FK: suggestion_user_id → Users.user_id FK: suggestion_admin_id → Admins.admin_user_id

Derived From: FD23 (suggestion_id → suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type)

Functional Dependency Enforced: FD23

Lossless Join Check:

  • suggestion_id was part of the composite key in Universal_Relation_1NF
  • Now suggestion_id becomes the sole primary key in Suggestions
  • Intersection: I = {suggestion_id}
  • FD23 guarantees suggestion_id uniquely determines all non-key attributes
  • Join with Universal_Relation_1NF on suggestion_id is lossless
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD23: suggestion_id → suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type
    • All attributes present ✓
    • Directly enforceable
  • Result: PRESERVED ✓

---

5.3 1NF Multivalued Relations – Already in 2NF

The four relations decomposed in the 1NF step (R1–R4: Case_Storage_Form_Factors, Case_Ps_Form_Factors, Case_Mobo_Form_Factors, Cooler_Cpu_Sockets) are already in 2NF because they contain only primary key attributes or attributes fully determined by their composite keys. No further decomposition is required.

Relation R1: Case_Storage_Form_Factors

Case_Storage_Form_Factors(component_id, pc_case_storage_form_factor, pc_case_storage_num_slots) PK: (component_id, pc_case_storage_form_factor) FK: component_id → Components.component_id

2NF Status: IN 2NF ✓

  • Composite primary key (component_id, pc_case_storage_form_factor)
  • The only non-key attribute pc_case_storage_num_slots depends on the entire composite key
  • No partial dependencies exist

Lossless Join Check:

  • Preserved from 1NF decomposition
  • Already verified as lossless in 1NF section
  • Result: LOSSLESS ✓

Dependency Preservation Check:

  • FD24: (component_id, pc_case_storage_form_factor) → pc_case_storage_num_slots
    • All attributes present ✓
    • Already verified as preserved in 1NF section
  • Result: PRESERVED ✓

---

Relation R2: Case_Ps_Form_Factors

Case_Ps_Form_Factors(component_id, pc_case_ps_form_factor) PK: (component_id, pc_case_ps_form_factor) FK: component_id → Components.component_id

2NF Status: IN 2NF ✓

  • Only key attributes; no non-key attributes to form partial dependencies

Lossless Join Check: LOSSLESS ✓ (preserved from 1NF)

Dependency Preservation Check: PRESERVED ✓ (FD26 preserved in 1NF)

---

Relation R3: Case_Mobo_Form_Factors

Case_Mobo_Form_Factors(component_id, pc_case_mobo_form_factor) PK: (component_id, pc_case_mobo_form_factor) FK: component_id → Components.component_id

2NF Status: IN 2NF ✓

  • Only key attributes

Lossless Join Check: LOSSLESS ✓ (preserved from 1NF)

Dependency Preservation Check: PRESERVED ✓ (FD25 preserved in 1NF)

---

Relation R4: Cooler_Cpu_Sockets

Cooler_Cpu_Sockets(component_id, cooler_cpu_socket) PK: (component_id, cooler_cpu_socket) FK: component_id → Components.component_id

2NF Status: IN 2NF ✓

  • Only key attributes

Lossless Join Check: LOSSLESS ✓ (preserved from 1NF)

Dependency Preservation Check: PRESERVED ✓ (FD27 preserved in 1NF)

---

6. Third Normal Form (3NF) Analysis

6.1 Transitive Dependency Analysis for Each 2NF Relation

Relation 1: Users

Users(user_id, username, password, email) PK: user_id FD: FD1 (user_id → username, password, email)

Non-key Attributes: username, password, email

Transitive Dependency Check:

  • Direct dependencies exist:
    • user_id → username (direct, via FD1)
    • user_id → password (direct, via FD1)
    • user_id → email (direct, via FD1)
  • Potential transitive chains: None
    • username does not determine any attribute
    • password does not determine any attribute
    • email does not determine any attribute

Conclusion: NO transitive dependencies exist

  • All non-key attributes depend directly on the primary key
  • 3NF Status: IN 3NF

---

Relation 2: Admins

Admins(admin_user_id) PK: admin_user_id FD: FD2 (admin_user_id → ∅)

Non-key Attributes: user_id

Transitive Dependency Check:

  • user_id is a foreign key (reference to Users.user_id)
  • Foreign keys are not derived attributes; they are stored references to another table
  • No chain exists because:
    • user_id is not functionally determined by any intermediate non-key attribute
    • user_id is directly stored in the relation as a reference
    • No further attributes depend on user_id within this relation

Conclusion: NO transitive dependencies exist

  • Foreign keys do not participate in transitive dependencies (they are direct references, not derived values)
  • 3NF Status: IN 3NF

---

Relation 3: Components

Components(component_id, component_name, component_brand, component_price, component_type, component_img_url) PK: component_id FD: FD3 (component_id → component_name, component_brand, component_price, component_type, component_img_url)

Non-key Attributes: component_name, component_brand, component_price, component_type, component_img_url

Transitive Dependency Check:

  • All non-key attributes depend directly on component_id:
    • component_id → component_name (direct)
    • component_id → component_brand (direct)
    • component_id → component_price (direct)
    • component_id → component_type (direct)
    • component_id → component_img_url (direct)
  • No attribute depends on another non-key attribute

Conclusion: NO transitive dependencies exist

  • All attributes are directly determined by the primary key
  • No chains of the form PK → B → A exist
  • 3NF Status: IN 3NF

---

Relation 4: Cpu

Cpu(component_id, cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp) PK: component_id FD: FD4 (component_id → cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp)

Non-key Attributes: cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp

Transitive Dependency Check:

  • All non-key attributes depend directly on component_id
  • No non-key attribute determines another non-key attribute

Conclusion: NO transitive dependencies exist

  • 3NF Status: IN 3NF

---

Relation 5–17: Gpu, Memory, Storage, Power_Supply, Motherboard, Pc_Case, Cooler, Memory_Card, Optical_Drive, Sound_Card, Cables, Network_Adapter, Network_Card

All 13 of these relations follow the identical pattern:

Pattern: ` Relation(component_id, [component_specific_attributes]) PK: component_id FD: component_id → [all dependent attributes] `

Transitive Dependency Check (for each):

  • All non-key attributes depend directly on component_id
  • No attribute depends on another non-key attribute
  • No chains of the form PK → B → A exist

Conclusion for Relations 5–17: NO transitive dependencies exist

  • 3NF Status: ALL IN 3NF

---

Relation 18: Build

Build(build_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved) PK: build_id FD: FD18 (build_id → build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved)

Non-key Attributes: build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved

Transitive Dependency Check:

  • Direct dependencies:
    • build_id → build_user_id (direct)
    • build_id → build_name (direct)
    • build_id → build_created_at (direct)
    • build_id → build_description (direct)
    • build_id → build_total_price (direct)
    • build_id → build_is_approved (direct)
  • build_user_id is a foreign key reference (not derived)
  • No non-key attribute determines another non-key attribute
  • No chains exist:
    • build_user_id does not determine build_name, build_created_at, etc.
    • Each attribute stands independently, directly determined by build_id

Conclusion: NO transitive dependencies exist

  • All attributes depend directly on the primary key
  • Foreign key does not create transitive dependencies
  • 3NF Status: IN 3NF

---

Relation 19: Build_Component

Build_Component(build_id, component_id, build_component_num_components) PK: (build_id, component_id) FD: FD19 ((build_id, component_id) → build_component_num_components)

Non-key Attributes: build_component_num_components

Transitive Dependency Check:

  • Only one non-key attribute exists: build_component_num_components
  • It depends directly on the composite primary key (build_id, component_id)

Conclusion: NO transitive dependencies exist

  • Only one non-key attribute present
  • Direct dependency on composite PK
  • 3NF Status: IN 3NF

---

Relation 20: Rating_Build

Rating_Build(build_id, user_id, rating_build_value) PK: (build_id, user_id) FD: FD20 ((build_id, user_id) → rating_build_value)

Non-key Attributes: rating_build_value

Transitive Dependency Check:

  • Only one non-key attribute: rating_build_value
  • Depends directly on (build_id, user_id)

Conclusion: NO transitive dependencies exist

  • Single non-key attribute
  • 3NF Status: IN 3NF

---

Relation 21: Favorite_Build

Favorite_Build(build_id, user_id) PK: (build_id, user_id) FD: FD21 ((build_id, user_id) → ∅)

Non-key Attributes: (none)

Transitive Dependency Check:

  • No non-key attributes exist
  • Therefore, no transitive dependencies can occur

Conclusion: NO transitive dependencies exist

  • 3NF Status: IN 3NF

---

Relation 22: Review

Review(review_id, review_build_id, review_user_id, review_content, review_created_at) PK: review_id Alt Key: (review_build_id, review_user_id) FD: FD22 (review_id → review_build_id, review_user_id, review_content, review_created_at)

Non-key Attributes: review_build_id, review_user_id, review_content, review_created_at

Transitive Dependency Check:

  • Direct dependencies on review_id:
    • review_id → review_build_id (direct, foreign key reference)
    • review_id → review_user_id (direct, foreign key reference)
    • review_id → review_content (direct)
    • review_id → review_created_at (direct)
  • review_build_id and review_user_id are foreign keys (not derived)
  • No non-key attribute determines another non-key attribute:
    • review_build_id does not determine review_content or review_created_at
    • review_user_id does not determine review_content or review_created_at
    • review_content does not determine review_created_at

Conclusion: NO transitive dependencies exist

  • All attributes depend directly on review_id
  • Foreign keys do not create transitive dependencies
  • 3NF Status: IN 3NF

---

Relation 23: Suggestions

Suggestions(suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type) PK: suggestion_id FD: FD23 (suggestion_id → suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type)

Non-key Attributes: suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type

Transitive Dependency Check:

  • All non-key attributes depend directly on suggestion_id:
    • suggestion_id → suggestion_user_id (direct, foreign key)
    • suggestion_id → suggestion_admin_id (direct, foreign key)
    • suggestion_id → suggestion_link (direct)
    • suggestion_id → suggestion_admin_comment (direct)
    • suggestion_id → suggestion_description (direct)
    • suggestion_id → suggestion_status (direct)
    • suggestion_id → suggestion_component_type (direct)
  • No non-key attribute determines another non-key attribute
  • No chains of form PK → B → A exist

Conclusion: NO transitive dependencies exist

  • All attributes depend directly on the primary key
  • Foreign keys are not derived values
  • 3NF Status: IN 3NF

---

Relation 24: Case_Storage_Form_Factors

Case_Storage_Form_Factors(component_id, pc_case_storage_form_factor, pc_case_storage_num_slots) PK: (component_id, pc_case_storage_form_factor) FD: FD24 ((component_id, pc_case_storage_form_factor) → pc_case_storage_num_slots)

Non-key Attributes: pc_case_storage_num_slots

Transitive Dependency Check:

  • Only one non-key attribute: pc_case_storage_num_slots
  • Depends directly on composite PK (component_id, pc_case_storage_form_factor)

Conclusion: NO transitive dependencies exist

  • 3NF Status: IN 3NF

---

Relations 25–27: Case_Ps_Form_Factors, Case_Mobo_Form_Factors, Cooler_Cpu_Sockets

All three relations follow the identical pattern:

Pattern: ` Relation(component_id, [attribute]) PK: (component_id, [attribute]) FD: ([attributes] → ∅) `

Transitive Dependency Check (for each):

  • No non-key attributes exist
  • Therefore, no transitive dependencies can occur

Conclusion for Relations 25–27: NO transitive dependencies exist

  • 3NF Status: ALL IN 3NF
Relation PK Type Non-Key Attributes Transitive Dependency? 3NF Status
Users Single (user_id) 3 attributes NO ✓ IN 3NF
Admins Single (admin_user_id) 0 attributes NO ✓ IN 3NF
Components Single (component_id) 5 attributes NO ✓ IN 3NF
Cpu–Network_Card (14 relations) Single (component_id) Variable NO ✓ IN 3NF
Build Single (build_id) 6 attributes NO ✓ IN 3NF
Build_Component Composite 1 attribute NO ✓ IN 3NF
Rating_Build Composite 1 attribute NO ✓ IN 3NF
Favorite_Build Composite 0 attributes NO ✓ IN 3NF
Review Single (review_id) 4 attributes NO ✓ IN 3NF
Suggestions Single (suggestion_id) 7 attributes NO ✓ IN 3NF
Case_Storage_Form_Factors Composite 1 attribute NO ✓ IN 3NF
Case_Ps_Form_Factors Composite 0 attributes NO ✓ IN 3NF
Case_Mobo_Form_Factors Composite 0 attributes NO ✓ IN 3NF
Cooler_Cpu_Sockets Composite 0 attributes NO ✓ IN 3NF

BCNF Analysis

Relation Primary Key FD Determinant Is Determinant a CK? Dependent Attributes BCNF Satisfied
Cpu component_id FD4 component_id YES (PK) cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp ✓ YES
Gpu component_id FD5 component_id YES (PK) gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length ✓ YES
Memory component_id FD6 component_id YES (PK) memory_type, memory_speed, memory_capacity, memory_modules ✓ YES
Storage component_id FD7 component_id YES (PK) storage_type, storage_capacity, storage_form_factor ✓ YES
Power_Supply component_id FD8 component_id YES (PK) power_supply_type, power_supply_wattage, power_supply_form_factor ✓ YES
Motherboard component_id FD9 component_id YES (PK) motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots ✓ YES
Pc_Case component_id FD10 component_id YES (PK) pc_case_cooler_max_height, pc_case_gpu_max_length ✓ YES
Cooler component_id FD11 component_id YES (PK) cooler_type, cooler_height, cooler_max_tdp_supported ✓ YES
Memory_Card component_id FD12 component_id YES (PK) memory_card_num_slots, memory_card_interface ✓ YES
Optical_Drive component_id FD13 component_id YES (PK) optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed ✓ YES
Sound_Card component_id FD14 component_id YES (PK) sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel ✓ YES
Cables component_id FD15 component_id YES (PK) cables_length_cm, cables_type ✓ YES
Network_Adapter component_id FD16 component_id YES (PK) network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas ✓ YES
Network_Card component_id FD17 component_id YES (PK) network_card_num_ports, network_card_speed, network_card_interface ✓ YES
Users user_id FD1 user_id YES (PK) username, password, email ✓ YES
Admins admin_user_id FD2 admin_user_id YES (PK) (none) ✓ YES
Components component_id FD3 component_id YES (PK) component_name, component_brand, component_price, component_type, component_img_url ✓ YES
Build build_id FD18 build_id YES (PK) build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved ✓ YES
Review review_id FD22 review_id YES (PK) review_build_id, review_user_id, review_content, review_created_at ✓ YES
Build_Component (build_id, component_id) FD19 (build_id, component_id) YES (PK) build_component_num_components ✓ YES
Rating_Build (build_id, user_id) FD20 (build_id, user_id) YES (PK) rating_build_value ✓ YES
Favorite_Build (build_id, user_id) FD21 (build_id, user_id) YES (PK) (none) ✓ YES
Suggestions suggestion_id FD23 suggestion_id YES (PK) suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type ✓ YES
Case_Storage_Form_Factors (component_id, pc_case_storage_form_factor) FD24 (component_id, pc_case_storage_form_factor) YES (PK) pc_case_storage_num_slots ✓ YES
Case_Ps_Form_Factors (component_id, pc_case_ps_form_factor) FD26 (component_id, pc_case_ps_form_factor) YES (PK) (none) ✓ YES
Case_Mobo_Form_Factors (component_id, pc_case_mobo_form_factor) FD25 (component_id, pc_case_mobo_form_factor) YES (PK) (none) ✓ YES
Cooler_Cpu_Sockets (component_id, cooler_cpu_socket) FD27 (component_id, cooler_cpu_socket) YES (PK) (none) ✓ YES

6. Final BCNF Decomposed Schema

6.1 Complete List of All Relations

  1. Users(user_id, username, password, email)
    • PK: user_id
  1. Admins(admin_user_id)
    • PK: admin_user_id
    • FK: admin_user_id → Users.user_id
  1. Components(component_id, component_name, component_brand, component_price, component_type, component_img_url)
    • PK: component_id
  1. Cpu(component_id, cpu_socket, cpu_cores, cpu_threads, cpu_base_clock, cpu_boost_clock, cpu_tdp)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Gpu(component_id, gpu_vram, gpu_tdp, gpu_base_clock, gpu_boost_clock, gpu_chipset, gpu_length)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Memory(component_id, memory_type, memory_speed, memory_capacity, memory_modules)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Storage(component_id, storage_type, storage_capacity, storage_form_factor)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Power_Supply(component_id, power_supply_type, power_supply_wattage, power_supply_form_factor)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Motherboard(component_id, motherboard_socket, motherboard_chipset, motherboard_form_factor, motherboard_ram_type, motherboard_num_ram_slots, motherboard_max_ram_capacity, motherboard_pci_express_slots)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Pc_Case(component_id, pc_case_cooler_max_height, pc_case_gpu_max_length)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Cooler(component_id, cooler_type, cooler_height, cooler_max_tdp_supported)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Memory_Card(component_id, memory_card_num_slots, memory_card_interface)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Optical_Drive(component_id, optical_drive_form_factor, optical_drive_type, optical_drive_interface, optical_drive_write_speed, optical_drive_read_speed)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Sound_Card(component_id, sound_card_sample_rate, sound_card_bit_depth, sound_card_chipset, sound_card_interface, sound_card_channel)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Cables(component_id, cables_length_cm, cables_type)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Network_Adapter(component_id, network_adapter_wifi_version, network_adapter_interface, network_adapter_num_antennas)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Network_Card(component_id, network_card_num_ports, network_card_speed, network_card_interface)
    • PK: component_id
    • FK: component_id → Components.component_id
  1. Build(build_id, build_user_id, build_name, build_created_at, build_description, build_total_price, build_is_approved)
    • PK: build_id
    • FK: build_user_id → Users.user_id
  1. Build_Component(build_id, component_id, build_component_num_components)
    • PK: (build_id, component_id)
    • FK: build_id → Build.build_id
    • FK: component_id → Components.component_id
  1. Rating_Build(build_id, user_id, rating_build_value)
    • PK: (build_id, user_id)
    • FK: build_id → Build.build_id
    • FK: user_id → Users.user_id
  1. Favorite_Build(build_id, user_id)
    • PK: (build_id, user_id)
    • FK: build_id → Build.build_id
    • FK: user_id → Users.user_id
  1. Review(review_id, review_build_id, review_user_id, review_content, review_created_at)
    • PK: review_id
    • Alt Key: (review_build_id, review_user_id)
    • FK: review_build_id → Build.build_id
    • FK: review_user_id → Users.user_id
  1. Suggestions(suggestion_id, suggestion_user_id, suggestion_admin_id, suggestion_link, suggestion_admin_comment, suggestion_description, suggestion_status, suggestion_component_type)
    • PK: suggestion_id
    • FK: suggestion_user_id → Users.user_id
    • FK: suggestion_admin_id → Admins.admin_user_id
  1. Case_Storage_Form_Factors(component_id, pc_case_storage_form_factor, pc_case_storage_num_slots)
    • PK: (component_id, pc_case_storage_form_factor)
    • FK: component_id → Components.component_id
  1. Case_Ps_Form_Factors(component_id, pc_case_ps_form_factor)
    • PK: (component_id, pc_case_ps_form_factor)
    • FK: component_id → Components.component_id
  1. Case_Mobo_Form_Factors(component_id, pc_case_mobo_form_factor)
    • PK: (component_id, pc_case_mobo_form_factor)
    • FK: component_id → Components.component_id
  1. Cooler_Cpu_Sockets(component_id, cooler_cpu_socket)
    • PK: (component_id, cooler_cpu_socket)
    • FK: component_id → Components.component_id
Note: See TracWiki for help on using the wiki.