With a clean candidate list, NOT IN can return TRUE, FALSE, or UNKNOWN.
three truth values
Read truth counts
This clean-list run has 2 TRUE rows, 2 FALSE rows, and 1 UNKNOWN row.
TRUE rows=2
NOT IN examples are tiny finite WHERE-style filters with SQL-style TRUE/FALSE/UNKNOWN behavior; correlation, optimizer behavior, execution cost, indexing, SQL dialect completeness, and database-product claims are out of scope.
UNKNOWN is not TRUE
The tested NULL row is UNKNOWN and does not pass WHERE.