NULL comparisons propagate UNKNOWN through composed predicates.

highlighted = computed this step

UNKNOWN from NULL comparisons

A comparison with NULL gives UNKNOWN, and composition carries that uncertainty.

NULL comparison UNKNOWN\text{NULL comparison UNKNOWN}

Read UNKNOWN rows

The composed AND expression has 2 UNKNOWN rows.

UNKNOWN rows=2\text{UNKNOWN rows}=2

Boolean-filter examples are tiny finite WHERE-style filters with SQL-style TRUE/FALSE/UNKNOWN logic; SQL dialect completeness, type coercion, optimizer behavior, indexing, and product claims are out of scope.

UNKNOWN from NULL comparisons: base rowsidagestatus130active217active3NULLactive440paused525NULL Boolean predicate evaluationsourcevaluestruthkepttrace0[1, 30, active]TRUEyes[age ge 18 -> TRUE, status eq active -> TRUE, AND(TRUE,TRUE) -> TRUE]1[2, 17, active]FALSEno[age ge 18 -> FALSE, status eq active -> TRUE, AND(FALSE,TRUE) -> FALSE]2[3, NULL, active]UNKNOWNno[age ge 18 -> UNKNOWN, status eq active -> TRUE, AND(UNKNOWN,TRUE) -> UNKNOWN]3[4, 40, paused]FALSEno[age ge 18 -> TRUE, status eq active -> FALSE, AND(TRUE,FALSE) -> FALSE]4[5, 25, NULL]UNKNOWNno[age ge 18 -> TRUE, status eq active -> UNKNOWN, AND(TRUE,UNKNOWN) -> UNKNOWN] Boolean filter output rowsidagestatus130active Boolean filter factsfactvalueinputRowCount5outputRowCount1trueRows1falseRows2unknownRows2rootKindandtreeAND(age ge 18, status eq active)rowOrdersource_order

Not TRUE

UNKNOWN rows are not TRUE, so this WHERE-style filter does not keep them.

UNKNOWN not kept\text{UNKNOWN not kept}

Summary

NULL comparisons make visible UNKNOWN facts, not hidden defaults.

visible UNKNOWN\text{visible UNKNOWN}