AVG
Average a set of values — NULLs are excluded from both the sum and the count, not treated as zero.
Syntax
AVG(expression)| Parameter | Type | Notes |
|---|---|---|
| expression* | numeric | The values to average. Equivalent to |
What it does
SQL playground
Loading editor…
⌘/Ctrl + Enter
NULL isn't zero
SQL playground
Loading editor…
⌘/Ctrl + Enter
Customer 4 has one order of $1000. If any order's amount were NULL,
AVG(amount) would still average only the non-NULL rows — it does not
divide by the total row count. AVG(10, NULL, 20) is 15, not 10.
Integer division
On some engines, averaging an integer column with integer arithmetic floors the result. Cast to a decimal/float type if you need fractional precision:
AVG(CAST(quantity AS DECIMAL)) -- or AVG(quantity * 1.0)SQLite and Postgres promote automatically for AVG(); this mostly bites on
engines that do strict integer division elsewhere in the same expression.
Gotchas
- "Average of averages" isn't the overall average unless every group has
the same number of rows. Weight it:
SUM(total) / SUM(count), notAVG(group_avg). - Outliers skew AVG more than they skew
MIN/MAX/MEDIAN-style measures — a report built onAVGalone can hide a long tail. - Missing rows silently change the denominator. A filter that drops rows
before
AVGruns shrinks both the sum and the count together — the average itself may look unaffected even though the underlying data changed a lot.
- SUM — the numerator AVG is built on.
- COUNT — the NULL-aware denominator.
- Running totals & moving averages — AVG as a rolling window instead of a collapsing aggregate.
Safety checklist
- decide whether missing values should be excluded or counted as zero
- confirm the column type doesn't force integer division
- verify the denominator is the row set you intend (
COUNT(expression)vsCOUNT(*))
Was this page helpful?