Lesson 3 / 25
NULL and Three-Valued Logic
Unknown is not false.
TRUE, FALSE and UNKNOWN
NULL means "unknown", so comparisons with NULL return UNKNOWN (shown as empty), not true or false: NULL = NULL is unknown. WHERE keeps only rows where the condition is TRUE, so unknown rows silently disappear. Use IS NULL, IS DISTINCT FROM (a NULL-safe comparison) and COALESCE for defaults. Aggregates skip NULLs: count(city) counts non-null values while count(*) counts rows, and city <> 'Pune' excludes NULL cities.
NULL comparisons and counting, run
I ran this with psql on PostgreSQL 16.2 against the course sample data (shown in the first section). Empty cells are NULL (unknown) results. 2 IN (1, NULL) is unknown rather than false. John has no city, so he is counted by count(*) but not count(city), and not matched by city <> 'Pune'.
SELECT NULL = NULL AS eq, NULL IS NULL AS is_null,
NULL IS DISTINCT FROM NULL AS distinct_from, 1 IN (1, NULL) AS in_hit,
2 IN (1, NULL) AS in_miss, COALESCE(NULL, 'fallback') AS coalesced;
SELECT count(*) AS all_rows, count(city) AS with_city,
count(*) FILTER (WHERE city <> 'Pune') AS not_pune
FROM customers;
Output:
eq | is_null | distinct_from | in_hit | in_miss | coalesced
----+---------+---------------+--------+---------+-----------
| t | f | t | | fallback
(1 row)
all_rows | with_city | not_pune
----------+-----------+----------
4 | 3 | 1
(1 row)Ask "what if this is NULL?" for every predicate
Especially for <>, NOT IN and outer-joined columns.
Quick check: What does NULL = NULL evaluate to?
- An error
- TRUE
- FALSE
- UNKNOWN (NULL)
Answer
UNKNOWN (NULL) — Use IS NULL or IS NOT DISTINCT FROM.