SQL: Why COUNT(column) Skips NULL Values
COUNT(*) counts rows, but COUNT(column) counts only non-NULL values.
The symptom
Two counts of the same table disagree. count(*) gives one number and count(shipped_date) gives a smaller one, so a report that should say "orders" quietly undercounts them. Neither query is broken; they are answering different questions.
Why it happens
count(*) counts rows. count(column) counts only rows where that column is not NULL. If a shipped date is missing for pending or cancelled orders, those rows disappear from the column count.
This behavior is useful when you mean "how many values are filled in," but misleading when you mean "how many rows exist."
The fix
Choose the count that matches the question: count(*) when you mean rows, count(column) when you mean values that are filled in. Both queries below claim to count Garden Shop orders.
select count(shipped_date) as orders
from ordersselect count(*) as orders
from ordersGarden Shop has 24 orders, and seven of them — three pending, three processing, one cancelled — have never shipped, so theirshipped_date is NULL andcount(shipped_date) stops at 17. Naming the column you count is what keeps this readable: count(*) as total_orders alongsidecount(shipped_date) as shipped_date_filled, andsum(case when shipped_date is null then 1 else 0 end) when you want the gap itself as a column.
Most aggregate functions ignore NULL values. count(*) is the special row-count form that does not inspect a specific column.
Learn more
Related
Find missing values with IS NULL.
Keep NULLs from silently changing filter results.
IS NULL, COALESCE, NULLIF, and null-safe logic.
IS NULL, COALESCE, NULLIF, and null-safe equality.