Module 03 Summary
The idea this module was built around
NULL means "not recorded". It does not mean zero, it does not mean empty, and it is not equal to itself. Every aggregate you write silently makes a decision about NULLs, and the decision changes the answer.
What you can now do
- Predict which rows a filter will silently drop, before running it
- Report a coverage percentage alongside every average
- Choose deliberately between skipping missing values and substituting a default
The trap this module removed
AVG skips NULLs; COALESCE(col, 0) does not. On the feedback table those two choices give 3.05 and 2.68 from identical data. Neither is a bug. Only one is defensible - and on a 1-to-5 rating scale, zero is not a possible response, so treating a missing rating as zero invents data.
The subtler half: WHERE country != 'IN' excludes the 300 customers with no recorded country, because three-valued logic makes NULL != 'IN' neither true nor false. Rows vanish and nothing warns you.
Figures worth remembering
Country coverage 93.8% (4,512 of 4,812) - ratings 88.0% (440 of 500) - test scores 80% (8 of 10).
Before you move on
Adopt one habit permanently: whenever you publish an average, publish the count it was computed over. A number without its denominator is not yet an answer.
