Skip to content
All writing Part 04 of 09 · One Operation, Many Engines
Engineering · 1 min read

count(*) vs count(col): It Comes Down to NULL

count(*) counts every row including NULLs; count(col) counts only non-NULL values. The gap between them is exactly your missing-value count, plus the CASE WHEN counting trick.

count() works in both ClickHouse and Spark. It’s standard SQL for counting rows. What actually trips people up every time is whether it counts NULLs.

count(expr) or count(DISTINCT expr)

  • COUNT(*) or COUNT(1)
    • * → all columns (a whitelist)
    • includes NULL
  • COUNT(col)
    • only counts rows where col is not NULL

The difference between the two is exactly the number of rows missing that value. It’s also the most direct way to answer “how many sign-ups didn’t fill in an email.”

Using CASE WHEN to count several conditions at once

SELECT
    COUNT(CASE WHEN salary > 100000 THEN 1 ELSE NULL END) AS high_earners,
    COUNT(CASE WHEN salary <= 100000 THEN 1 ELSE NULL END) AS standard_earners
FROM employees;
  • The trick: COUNT(col) only increments on non-NULL, so write the branch you don’t want counted as NULL.

References

Related: back to the Cross-Engine DB Query overview, or see it inside the portable SQL core.

Tags #sql #databases
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Life RecordYoutube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration