4.4.23 · D2Databases

Visual walkthrough — ER diagrams — entities, attributes, relationships, cardinality

2,027 words9 min readBack to topic

We will build one central result, the pair-counting law and watch the three cardinality rules fall out of it as pictures.


Step 1 — What a relationship is: a pair of dots joined by string

WHAT. Draw two boxes. The left box is entity set ; inside it live dots — each dot is one entity instance (one real student, one real department). The right box is entity set . A relationship instance is nothing more mysterious than one piece of string tying a left dot to a right dot.

WHY. Before we can count how many relationships are possible, we must agree what a single relationship looks like. It looks like a string between two dots — an ordered pair .

PICTURE. In the figure, dot on the left is tied to dot on the right. That one blue string is one relationship instance.


Step 2 — Counting all possible strings: the rule of product

WHAT. Now allow every left dot to be tied to every right dot, with no rules yet. Count the strings. In the figure and , and the grid of thin strings has crossing points.

WHY. We use multiplication here — not addition — because of the rule of product: for each of the 3 left dots there are 4 independent choices of partner on the right. "For each … there are …" is precisely the phrase that means multiply. Adding would answer "how many dots total", a different question.

PICTURE. Each left dot fans out to all 4 right dots (one colour per source dot). Count one fan: 4 strings. There are 3 fans. Total strings = the whole grid.


Step 3 — M:N: the ceiling is allowed, so no single column can hold it

WHAT. In a Many-to-Many relationship every left dot may connect to many right dots and every right dot may connect to many left dots. Nothing is forbidden — the full grid of strings is legal.

WHY. Ask the decisive question: could a left dot store its partner in one column? No — a column holds one value, but has many partners (). Symmetrically a right dot has many left partners. A single column cannot hold a set, so neither box can absorb the relationship.

PICTURE. Look at dot : three orange strings leave it. Look at : two strings arrive. Because both sides fan out, we externalise the strings into a third box — a junction table — where each row is one string .


Step 4 — 1:N: forbidding reuse on the "one" side collapses the ceiling to

WHAT. In One-to-Many (one Department → many Employees), we forbid a strings: each right dot (each employee) may have exactly one left partner (department). Left dots may still fan out.

WHY this changes the count. Count strings by walking the right box instead of the left. Each of the right dots contributes exactly one string (it is allowed only one partner). So: The ceiling never appears, because the "one" side (left) cannot be reused as a fresh choice by each right dot — each right dot is nailed to a single left dot.

PICTURE. Every right dot has exactly one string leaving it (count them: strings, no more). Some left dots collect several strings; that is fine.


Step 5 — Where the foreign key lives (the payoff)

WHAT. Because each right dot (Employee) has exactly one left partner (Department), that partner fits in a single column on the right dot. We write the department's name (its key) onto each employee's row. That column is the foreign key.

WHY on the many side and not the one side? Try the reverse: store employees on the Department row. Department has three employees → you would need a list in one cell, which breaks 1NF (Normalization — 1NF, 2NF, 3NF). Storing on the many side needs only one value per row — legal. This is the rule "FK lives on the many side; the many holds the one's name."

PICTURE. The dept_id column appears on the right (Employee) rows; each cell holds exactly one left-dot label. See it as cutting each string and writing the far end's label into a box beside the near dot.

See Relational Model — tables, keys, foreign keys and Cardinality and JOIN behaviour.


Step 6 — 1:1: forbid reuse on both sides → the ceiling collapses to

WHAT. In One-to-One (Person — Passport) each dot on either side has at most one partner. Both fans are switched off.

WHY . A string uses up one left dot and one right dot; neither can be reused. So the number of strings cannot exceed the smaller box — once the smaller box runs out of unused dots, no more strings can be drawn. If , at most strings.

PICTURE. A clean one-to-one matching: left dots pair off with distinct right dots; the extra right dots sit unmatched (partial participation). Implement with the FK on either side plus a UNIQUE constraint, which enforces "at most one" — see SQL CREATE TABLE and constraints.


Step 7 — Degenerate cases: empty box and a single dot

WHAT. Two edge cases the formula must survive:

  • Empty box: . Then — no dots on one side means no strings can start, so zero relationships. The picture is one empty box: nothing to tie.
  • Single dot with total participation on a 1:N: , every right dot must point at it. Then all strings converge on the one left dot — a perfect fan-in, and , matching Step 4's ceiling exactly.

WHY show these. A rule you cannot push to its extremes is a rule you do not understand. Zero and one are where wrong formulas expose themselves.

PICTURE. Left panel: empty , no strings. Right panel: one left dot, four right dots all tied to it — the maximal 1:N fan-in.


The one-picture summary

Everything above is one idea seen four ways: start with the full grid of strings, then switch off fans to get each cardinality — and whichever side is left holding a single partner is the side that can carry the foreign key in one column.

Recall Feynman retelling — the whole walk in plain words

Picture two boxes of dots and a ball of string. One string tying a left dot to a right dot is one "fact that they're connected". If I let everything connect to everything, the most strings I can draw is left-dots times right-dots — because each left dot can independently reach every right dot (that's why I multiply, not add).

Now I turn strings off to make rules. Many-to-many: leave everything on — both sides fan out, so I can't write a partner in a single box beside any dot; I keep a separate notebook where each line is one string. That notebook is the junction table. One-to-many: I say every right dot gets only one string. Now if I walk the right dots, each hands me exactly one string, so the total is just the number of right dots — not the big product. And since each right dot has a single partner, I can just write that partner's name in a little box beside it. That little box is the foreign key, and it lives on the "many" side because that's the side with exactly one partner to name. One-to-one: every dot on both sides gets at most one string, so the smaller box runs out first — the max is the smaller count, and a UNIQUE box on either side enforces it. Empty box: no dots, no strings, zero. That's the entire theory: count strings, switch off fans, and let whoever holds a single partner carry the name.