erDiagram
ORDERS {
int order_id
string customer_name
string city
string product
float price
int quantity
}
Normalization, JOINs
2026-04-02
Relational databases do not start with JOINs.
They start with structure.
Normalization explains why data is split.
JOINs explain how it is recombined.
Imagine storing everything in one table.
| order_id | customer_name | city | product | price | quantity |
|---|---|---|---|---|---|
| 1 | Anna | Yerevan | Phone | 500 | 1 |
| 2 | Anna | Yerevan | Case | 20 | 2 |
| 3 | Arman | Gyumri | Phone | 500 | 1 |
\(\downarrow\) This structure is fragile.
A table is in 1NF if:
The previous table already satisfies 1NF.
Yet it is still badly designed.
Because multiple entities are mixed.
erDiagram
ORDERS {
int order_id
string customer_name
string city
string product
float price
int quantity
}
A table is in 2NF if:
1NFIn the unnormalized table:
(order_id, product)
Because:
Partial dependencies exist.
This violates 2NF.
flowchart LR
K[(order_id, product)]
K --> Q[quantity]
order_id --> C[customer_name, city]
product --> P[price]
We separate real-world entities.
| customer_id | customer_name | city |
|---|
| product_id | product | price |
|---|
| order_id | customer_id |
|---|
| order_id | product_id | quantity |
|---|
Key: (order_id, product_id)
Quantity depends on the entire key.
2NF achieved.
erDiagram
CUSTOMERS {
int customer_id PK
string customer_name
string city
}
PRODUCTS {
int product_id PK
string product
float price
}
ORDERS {
int order_id PK
int customer_id FK
}
ORDER_ITEMS {
int order_id FK
int product_id FK
int quantity
}
CUSTOMERS ||--o{ ORDERS : places
ORDERS ||--o{ ORDER_ITEMS : contains
PRODUCTS ||--o{ ORDER_ITEMS : included_in
A table is in 3NF if:
customer_id → city
city → country
Therefore:
customer_id → country (indirectly)
This violates 3NF.
flowchart LR
customer_id --> city
city --> country
customer_id --> country
| country_id | country |
|---|
| city_id | city | country_id |
|---|
| customer_id | customer_name | city_id |
|---|
erDiagram
CUSTOMERS {
int customer_id PK
string customer_name
int city_id FK
}
CITIES {
int city_id PK
string city
int country_id FK
}
COUNTRIES {
int country_id PK
string country
}
CUSTOMERS ||--|| CITIES : lives_in
CITIES ||--|| COUNTRIES : belongs_to
flowchart TB
A[Unnormalized] --> B[1NF]
B --> C[2NF]
C --> D[3NF]
In practice:
Most transactional systems stop at 3NF or BCNF.
BCNF: Boyce–Codd Normal Form