4.4.1 · D4Databases

Exercises — Relational model — tables, rows, columns, NULL

2,695 words12 min readBack to topic

This page assumes only the parent note's picture: a table is a grid of facts — columns name the kind of fact, rows are records, and NULL means "value unknown / absent."

We will reuse this one table throughout. Everything refers back to it:

Table Student:

id name age major gpa
1 Asha 20 CS 3.8
2 Ravi NULL Physics NULL
3 Mira 22 NULL 3.1
4 Dev 19 CS 3.1
Figure — Relational model — tables, rows, columns, NULL

Look at the picture: two cells are shaded — those are NULL, the "no clue" boxes. Notice they are empty of any claim, not filled with a zero.


Level 1 — Recognition

L1.1 — Count the shape

Recall Solution

WHAT we do: apply the two definitions — count columns for degree, count rows for cardinality.

  • Columns are id, name, age, major, gpa → 5 columns → degree = 5.
  • Rows are Asha, Ravi, Mira, Dev → 4 rows → cardinality = 4.

WHY it works: degree is the grid's width and cardinality is its height. A NULL cell still counts — the row and column exist; only the value is missing.

L1.2 — Name the marker

Recall Solution

The marker is NULL. It does not equal 0 (a known number) and does not equal '' (a known empty string) — those are values, NULL is the absence of one.

The NULL-vs-NULL subtlety: SQL does not say NULL = NULL is FALSE. It says the comparison is UNKNOWN (printed as NULL): you cannot prove two unknowns equal because you don't know either one. Because = never returns TRUE for NULL, the only reliable test for "is this cell missing?" is IS NULL (or IS NOT NULL), which returns a real TRUE/FALSE.


Level 2 — Application

L2.1 — Apply a WHERE filter

Recall Solution

WHAT we do: test the condition gpa = 3.1 on every row; keep a row only if the result is TRUE.

  • Asha: 3.8 = 3.1 → FALSE → drop.
  • Ravi: NULL = 3.1UNKNOWN → drop (not TRUE).
  • Mira: 3.1 = 3.1 → TRUE → keep.
  • Dev: 3.1 = 3.1 → TRUE → keep.

Answer: Mira, Dev. WHY Ravi drops: comparing a known number to an unknown gives UNKNOWN, and WHERE only keeps TRUE.

L2.2 — Substitute a default with COALESCE

Recall Solution

WHAT COALESCE does: COALESCE(x, d) returns x if x is not NULL, else d.

  • Asha: 3.8 (not NULL) → 3.8
  • Ravi: NULL → default → 0.0
  • Mira: 3.13.1
  • Dev: 3.13.1

Result list: [3.8, 0.0, 3.1, 3.1]. WHY use it: it turns "unknown" into a chosen stand-in so later arithmetic doesn't collapse to NULL.


Level 3 — Analysis

L3.1 — Predict the 3VL result

Recall Solution

Treat NULL (call it U) as "TRUE or FALSE, can't tell." The figure below is a colour-coded truth table — read it like this:

Figure — Relational model — tables, rows, columns, NULL

How to read the figure (alt text): it has two blocks. The left block, "AND", lists three rows: FALSE AND U = FALSE (orange result), TRUE AND U = U (magenta result), U AND U = U. The right block, "OR", lists TRUE OR U = TRUE (violet result), FALSE OR U = U, U OR U = U. Colours: violet = TRUE, orange = FALSE, magenta = UNKNOWN. The caption reminds you: the known side wins whenever it already forces the answer.

Now the five parts:

  • (a) FALSE AND U: AND is TRUE only if both TRUE. One side is already FALSE → whole thing FALSE no matter what U is → FALSE.
  • (b) TRUE OR U: OR is TRUE if either is TRUE. One side is already TRUE → TRUE.
  • (c) TRUE AND U: result depends entirely on U — could be TRUE or FALSE → UNKNOWN.
  • (d) U OR U: both unknown, could go either way → UNKNOWN.
  • (e) NOT U: NOT flips TRUE↔FALSE, but if we can't tell whether U is TRUE or FALSE, we equally can't tell what its opposite is → UNKNOWN. (This is why NOT (age = 20) still drops Ravi: flipping an unknown stays unknown.)

WHY: whenever the known side already forces the answer, the unknown can't change it. Otherwise — including any NOT applied to an unknown — the answer is genuinely unknown.

L3.2 — The vanishing row

Recall Solution

WHAT we do: evaluate the condition per row.

  • Asha (20): 20>21 FALSE OR 20<=21 TRUE → TRUE → keep.
  • Ravi (NULL): NULL>21=U OR NULL<=21=U → U OR U = UNKNOWN → drop.
  • Mira (22): 22>21 TRUE → TRUE → keep.
  • Dev (19): 19<=21 TRUE → TRUE → keep.

Answer: 3 rows (Asha, Mira, Dev). It looks like it should return all 4 ("every age is either >21 or ≤21"), but Ravi's unknown age makes both halves UNKNOWN, so he's excluded. Fix to get all 4: append OR age IS NULL.


Level 4 — Synthesis

L4.1 — Combine COUNT semantics

Recall Solution

Rule: COUNT(*) counts rows; COUNT(col) counts rows where col is not NULL.

  • (a) COUNT(*) = 4 rows → 4.
  • (b) COUNT(age): ages are 20, NULL, 22, 19 → 3 non-NULL → 3.
  • (c) COUNT(gpa): 3.8, NULL, 3.1, 3.1 → 3 non-NULL → 3.
  • (d) COUNT(major): CS, Physics, NULL, CS → 3 non-NULL → 3.

WHY the difference: * means "just tell me how many records exist," while COUNT(col) means "how many records have a known value in that column."

L4.2 — Averages skip NULL

Recall Solution

Plain AVG(gpa): non-NULL gpas are 3.8, 3.1, 3.1.

  • Sum = 3.8 + 3.1 + 3.1 = 10.0. Count = 3.
  • Average = 10.0 ÷ 3 = 3.333… ≈ 3.333.

After COALESCE: now the values are 3.8, 0.0, 3.1, 3.1 — four known numbers.

  • Sum = 3.8 + 0.0 + 3.1 + 3.1 = 10.0. Count = 4.
  • Average = 10.0 ÷ 4 = 2.5.

WHY they differ: plain AVG treats Ravi's gpa as "not there" (dropped from both sum and count). COALESCE claims Ravi scored 0.0, dragging the mean down. Same data, two different questions — choose deliberately.


Level 5 — Mastery

L5.1 — Design a key & justify uniqueness

Recall Solution

(a) Classical relational model: Codd's pure model in first normal form requires every attribute to hold exactly one atomic value from its domain — it does not permit missing values at all; NULL was a later, controversial addition precisely because pure theory has no slot for "no value." So strictly, a row with age=NULL is not a well-formed tuple of the pure relation; the whole three-valued-logic machinery exists only because practical SQL bolted NULL on top. (Even setting NULL aside, a relation is a set, so the separate rule that forbids duplicate rows would still apply.) (b) Real SQL with PK on id: a PRIMARY KEY forces id to be unique and NOT NULL. Row with id=1 already exists → the insert is rejected. This is why keys matter: real tables are multisets and would otherwise permit two different students sharing id=1, breaking the "one id ↔ one student" promise. Constraint that fixes it: declare id PRIMARY KEY (or UNIQUE), which forbids duplicate identifiers. See Foreign Keys and Referential Integrity for why other tables can then safely point at id.

L5.2 — Prove a rewrite is NULL-safe

Recall Solution

Semantics: major = 'CS' is UNKNOWN for Mira (NULL vs a known string), so WHERE drops her — this is correct behaviour, not a bug. If we want to include unknowns we must say so. Condition: WHERE major = 'CS' OR major IS NULL. Row-by-row:

  • Asha (CS): TRUE OR FALSE = TRUE → keep.
  • Ravi (Physics): FALSE OR FALSE = FALSE → drop.
  • Mira (NULL): UNKNOWN OR TRUE = TRUE (OR with a TRUE is TRUE) → keep.
  • Dev (CS): TRUE OR FALSE = TRUE → keep.

Answer: Asha, Mira, Dev (3 rows). WHY it works: IS NULL returns a real TRUE for Mira, and TRUE OR anything = TRUE, rescuing her from the vanishing-row trap.


Active recall

Recall Rapid re-test (recall before revealing)

Degree & cardinality of Student? ::: 5 and 4. COUNT(*) vs COUNT(age) here? ::: 4 vs 3. Rows returned by WHERE age > 21 OR age <= 21? ::: 3 (Ravi's NULL age escapes both). AVG(gpa) vs AVG after COALESCE(gpa,0)? ::: 3.333 vs 2.5. FALSE AND NULL / TRUE OR NULL / NOT NULL? ::: FALSE / TRUE / UNKNOWN. One condition for CS-or-unknown majors? ::: major='CS' OR major IS NULL.


Connections

  • Primary Keys and Uniqueness — L5.1's fix for duplicate ids
  • Foreign Keys and Referential Integrity — why unique ids let tables point at each other
  • SQL SELECT and WHERE — every WHERE exercise here
  • Normalization — first normal form and why pure relations dislike NULL
  • Data Types and Domains — what each column may legally hold
  • COALESCE and NULL handling functions — L2.2 and L4.2
Degree and cardinality of the Student table (5 cols, 4 rows)?
Degree 5, cardinality 4.
How many rows pass WHERE age > 21 OR age <= 21?
3 — the NULL age fails both comparisons.
COUNT(gpa) when one gpa is NULL out of 4 rows?
3 (NULLs are skipped).
AVG(gpa) over 3.8, NULL, 3.1, 3.1?
10.0 / 3 = 3.333 (NULL skipped).
Same after COALESCE(gpa, 0.0)?
10.0 / 4 = 2.5 (NULL became a real 0).
NOT NULL in three-valued logic evaluates to?
UNKNOWN (flipping an unknown stays unknown).
Condition to select CS or unknown-major students?
major = 'CS' OR major IS NULL.
Why does PRIMARY KEY reject a second id=1?
It enforces uniqueness and NOT NULL on the key.
Does the classical relational model (1NF) allow NULL?
No — NULL is a later addition; pure 1NF requires one atomic value per attribute.