Problems / Column NULL Audit / Editorial
The output rows describe *columns*, so no GROUP BY over data values can produce them — this is a manual unpivot of four independent whole-table aggregates:
'email' AS column_name
COUNT(*) - COUNT(email) AS null_count
ROUND((COUNT(*) - COUNT(email)) * 100.0 / COUNT(*), 2) AS null_pct
UNION ALL
ORDER BY column_name
The core trick is COUNT(*) vs COUNT(col): COUNT(*) counts rows, COUNT(col) counts non-NULL values, so their difference is the NULL count. The empty-string email in the data is deliberately not counted — '' is a value, and treating it as NULL is a classic profiling bug.
COUNT(*)
COUNT(col)
''
COUNT(*) - COUNT(col) is the canonical NULL profiler, and it distinguishes NULL from empty string automatically. source has no NULLs and still reports a row (0 / 0.00) because each UNION ALL branch is a whole-table aggregate that always yields exactly one row — unlike a filtered GROUP BY, whose empty groups simply vanish.
COUNT(*) - COUNT(col)
source
Solve Column NULL Audit yourself →