Why Your AI's COUNT Is Lower Than the Number of Rows
Asked how many customers you have and got a lower number than the table actually has. COUNT(column) skips NULL values in that column — COUNT(*) does not. Same table, two different counts, no error.
You ask "how many customers do we have?" The AI comes back with 8,412. You glance at the admin UI — 9,103. Nothing errored. The query looks fine. The difference is often which COUNT it used.
Two functions that look interchangeable
SELECT COUNT(*) FROM customers;
SELECT COUNT(email) FROM customers;
Both compile. Both run. They answer different questions:
COUNT(*)— how many rowsCOUNT(email)— how many rows whereemailis not NULL
If 691 customers have no email on file, those two queries disagree by exactly 691, with no warning. The AI often reaches for COUNT(email) because the question mentioned customers and email is a "real" identifying column — it sounds more precise than *. It's more precise about the wrong thing.
COUNT(DISTINCT email) has the same NULL skip, plus it collapses duplicates. That's "how many unique filled-in emails," not "how many customers."
Why this is easy to miss
Unlike a syntax error, both answers are correct for the SQL that ran. The mismatch only shows up if you already know the real row count — which is exactly the known-answer check worth doing on any headline number.
This is also a cousin of SUM returning NULL instead of zero: aggregates treat NULL as "nothing to count/sum," not as a row that still exists. COUNT is the one people assume is immune because COUNT(*) is immune. The moment a column name goes inside the parentheses, that immunity is gone.
How to catch it
Ask for both in the same breath:
How many customer rows are there (COUNT(*))?
How many have a non-NULL email (COUNT(email))?
Show both numbers and the SQL.
If they differ, you now know how incomplete that field is — useful on its own — and you know which number answers "how many customers."
The prompt that heads this off
For "how many X" questions, use COUNT(*) or COUNT(primary_key),
not COUNT(some_nullable_column). If you use COUNT(column), say
explicitly that you're counting non-NULL values in that column.
The short version
COUNT(email) is not a fancier COUNT(*). It's a different metric. If the AI's headcount is a few hundred short of the admin UI, check the parentheses before you check the filters.
Read-only MCP gateway: mcpserver.design.
Related reading: