Decomposition: lossless joins and dependency preservation
Normalizing means splitting a table into smaller ones. A good split has two properties.
Lossless join
A decomposition is lossless if joining the pieces gives back exactly the original rows: nothing lost, nothing extra.
Student(StudentID, DepartmentID, DepartmentName) with DepartmentID → DepartmentName, split into:
StudentDepartment(StudentID, DepartmentID)Department(DepartmentID, DepartmentName)
The shared column, DepartmentID, determines every column of Department, so each student row joins to exactly one department row. Lossless.
The test for splitting R into R1 and R2: the shared columns must be a key of at least one side.
(R1 ∩ R2) → R1, or(R1 ∩ R2) → R2
Lossy decomposition
Split the wrong way and the join invents rows (spurious tuples). Take:
| Student | Hobby | Language |
|---|---|---|
| Asha | Music | Hindi |
| Asha | Chess | English |
Here, suppose the rows mean "Asha does Music in Hindi" and "Chess in English": the pairs matter. Split into (Student, Hobby) and (Student, Language), join on Student, and you get four rows, including "Music in English", which was never true. Student isn't a key of either piece, so the test above fails.
Compare section 1.8.4: when hobbies and languages are independent, the same split is exactly right. The data alone can't tell you; the business rules can.
Dependency preservation
A decomposition is dependency-preserving if every original FD can still be checked inside a single table, without joining.
That matters because a database enforces rules cheaply within one table (a primary key, a unique constraint), but a rule that spans tables needs triggers or application code, which are slower and easy to get wrong.