Skip to content
Part IA Michaelmas Term

Breaking Tables Down to Reduce Redundancy

The decomposition strategy

To eliminate redundancy, we decompose DirectedComplete into three tables: one for each entity set and one for the relationship.

Movies(movie_id, title, year)
People(person_id, name, birthYear)
Directed(movie_id, person_id)

Entity tables

Each E/R entity becomes a relational table. The entity’s attributes become the table’s columns. The entity’s key becomes the table’s primary key.

EntityTable
MoviesMovies(movie_id, title, year)
PeoplePeople(person_id, name, birthYear)

Each row in Movies stores exactly one movie. Each row in People stores exactly one person. No duplication.

Relationship tables

Each E/R relationship also becomes a relational table. For the Directed relationship (a many-to-many relationship between Movies and People), we create:

Directed(movie_id, person_id)

The key of Directed is the combination (movie_id, person_id). This is called an “all-key” table because every column is part of the primary key. This pattern is standard for many-to-many relationships: the relationship table has no attributes of its own beyond the foreign keys to the participating entities.

A concrete example

Suppose the database contains the following:

Movies:

movie_idtitleyear
m01The Matrix1999
m02Speed Racer2008
m03Cloud Atlas2012

People:

person_idnamebirthYear
p01Lana Wachowski1965
p02Lilly Wachowski1967

Directed:

movie_idperson_id
m01p01
m01p02
m02p01
m02p02
m03p01
m03p02
m03NULL

Each fact is stored in exactly one place. Lana Wachowski’s name appears only once, in the People table. If we need to correct it, we update one row.

Reconstructing the original view

The original DirectedComplete table can be reconstructed using a SQL JOIN:

SELECT movie_id, title, year, person_id, name, birthYear
FROM movies
  JOIN directed ON directed.movie_id = movies.movie_id
  JOIN people ON people.person_id = directed.person_id;

The join combines the three tables on their common key columns, producing exactly the same columns we had in DirectedComplete — but without the redundancy.

The fundamental trade-off

Single-table designDecomposed design
RedundancyHighNone (or minimal)
Insertion anomaliesPresentAbsent
Deletion anomaliesPresentAbsent
Update anomaliesPresentAbsent
Query simplicitySimple (one table)Requires JOINs
Write performancePoor (write amplification)Good

The decomposed design is the “good” design: we accept the cost of writing JOIN queries in exchange for eliminating redundancy and its associated anomalies. JOINs are the price we pay for a well-normalised schema.

Both entities and relationships are tables

A key insight: in the relational model, both E/R entities and E/R relationships are implemented as tables. There is no separate construct for relationships. A relationship table is distinguished only by its content — it contains foreign keys referencing entity tables.

Summary

  • Decompose a big table into one table per entity set and one per relationship.
  • Entity tables store attributes; relationship tables store foreign keys.
  • Many-to-many relationships produce all-key tables.
  • JOINs reconstruct the combined data when needed.
  • The cost of JOINs is the price of eliminating redundancy and anomalies.