AVG() calculates the arithmetic mean of non-NULL input values, with a denominator equal to the number of known values.
An average sale amount should say whether it describes known amounts, every recorded sale, or an average of group averages. Those measures are not interchangeable. AVG supplies the first meaning unless you deliberately transform its input.
This reference adds detail to the main course. You can read it independently: the small database below supplies every table and row used in the examples. Start with the question each query answers, then compare the returned values with the data rather than memorising a line of syntax.
Set up the practice database
Run this setup once in a new practice database, before the examples. It uses four customers and six sales. Ana has two sales, Ben has one, Cara has two, and Dev has none.
Sale 106 has no customer link; sale 104 has an unknown amount. These deliberate test cases expose missing information and unmatched relationships.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(40) NOT NULL,
city VARCHAR(40),
manager_id INTEGER
);
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
customer_id INTEGER,
amount DECIMAL(10,2),
status VARCHAR(20) NOT NULL,
created_on DATE NOT NULL
);
INSERT INTO customers (id,name,city,manager_id) VALUES
(1,'Ana','Leeds',NULL),(2,'Ben','Leeds',1),
(3,'Cara','Porto',1),(4,'Dev',NULL,2);
INSERT INTO sales (id,customer_id,amount,status,created_on) VALUES
(101,1,10,'paid','2026-01-01'),
(102,1,30,'pending','2026-01-02'),
(103,2,20,'paid','2026-01-02'),
(104,3,NULL,'pending','2026-02-01'),
(105,3,20,'paid','2026-02-02'),
(106,NULL,5,'paid','2026-02-03');An amount of zero would be a known value. The NULL amount here means the value is unknown. A customer with no matching sale differs from a sale whose customer_id is NULL.
The primary keys identify individual records even when amounts or cities repeat. Dates use year-month-day format. The examples specify sorting whenever order matters; insertion order alone does not guarantee display order.
How AVG() works
The known amounts sum to eighty-five and there are five of them, so AVG(amount) is seventeen. The NULL amount is excluded from both the sum and denominator. Dividing eighty-five by all six sale records answers a different question and treats the missing amount as if it contributed zero. That can be a valid business policy only if it is explicitly intended, not an accidental consequence of choosing the wrong count.
AVG(COALESCE(amount,0)) includes one zero for the missing sale and divides by six. COALESCE(AVG(amount),0) instead leaves the normal known-value denominator intact and supplies a fallback only when the resulting average is NULL. These two expressions place the missing-value policy at different stages. The example table deliberately contains an unknown amount so you can observe the distinction before using averages in a real report.
Averages of averages and weighting
Group averages should not normally be averaged again without weights. Customer 1’s known amounts average twenty, customer 2’s average twenty, and customer 3’s known average is twenty. Other datasets can have very different group sizes, making an unweighted average of customer averages diverge from the overall transaction average. To combine groups, retain each group’s sum and known-value count, then divide total sums by total counts. This is the weighted approach that preserves the original observation grain.
The result type depends on the input type and engine. Some engines can return an integer result for an average over integer input, while others promote the calculation. Cast to an appropriate decimal type if fractional results are required, and round for display after calculation rather than rounding every input indiscriminately. AVG ignores an empty filtered input and yields NULL because no mean exists. A zero denominator in a hand-written SUM/COUNT formula must also be guarded, typically with NULLIF.
MySQL, PostgreSQL, SQL Server and SQLite
AVG is shared by all four systems. SQL Server AVG over integer input returns an integer-type result, so cast when fractional precision is needed. SQLite’s AVG returns a floating-point approximation. Other engines’ precision and scale rules depend on the numeric input type; verify them for financial reporting.
Check the engine-specific syntax and version requirements in SQL Server AVG.
Practice task and worked solution
Calculate the average known amount for paid sales. Explain which four amounts enter the denominator.
Try the task before reading its worked solution. The supplied rows make the expected answer checkable by hand.
SELECT AVG(amount) AS paid_mean
FROM sales WHERE status='paid';paid_mean
13.75Paid sales have amounts ten, twenty, twenty and five. Their sum is fifty-five and their count is four, so the mean is 13.75. The pending sale with a missing amount cannot affect either side of this paid-only calculation.
Compare AVG(amount) with AVG(COALESCE(amount,0)). The first is seventeen; the second uses six observations and is approximately 14.167. Then filter to the missing amount alone: AVG is NULL rather than zero. Explain how replacing a final unknown average differs from treating a missing input measurement as a known zero before the denominator is formed.
SQL AVG Function: Averages, NULL Values and Weighted Means Syntax
AVG()
SELECT AVG(amount) AS mean_known_amount FROM sales;SQL AVG Function: Averages, NULL Values and Weighted Means Summary
AVG(column)divides the sum of non-NULLvalues by the number of non-NULLvalues.SUM(amount) / COUNT(*)uses every row as the denominator and answers a different question.- Averaging group averages gives each group equal weight; use totals and counts for a weighted mean.
- In SQL Server,
AVGof an integer column returns an integer, so cast to a decimal type first. - Show the number of observations beside an average so readers know how much data it rests on.
SQL AVG Function: Averages, NULL Values and Weighted Means Examples
Each example shows the code, the output it produces and what each part does.
The mean of known amounts
AVG uses the five present amounts, not all six records. Their sum is eighty-five, and eighty-five divided by five is seventeen. The DECIMAL input expresses fractional numeric intent even though this particular mean has no fractional part.
SELECT AVG(amount) AS mean_known_amount FROM sales;mean_known_amount
17Common SQL AVG Function: Averages, NULL Values and Weighted Means Mistakes
Dividing SUM by COUNT(*)
SUM(amount)/COUNT(*) uses all six rows as the denominator and does not reproduce AVG(amount). COUNT(amount) is the matching known-value count, but manual division must still guard zero and type conversion. AVG is clearer when a normal arithmetic mean of known values is the intended measure.
SQL AVG Function: Averages, NULL Values and Weighted Means in Real Projects
Averages with context in performance reports
A sales-performance report can show the mean known amount alongside the number of observations and missing amounts. That context tells a reader whether the average is based on many complete records or a small incomplete sample. If you compare customer groups, keep the unit of observation consistent.
Carry the number of known observations with any average used for comparison. A mean based on one complete value is different evidence from a mean based on many records. When combining group reports, preserve sums and known counts so a weighted recombination can recover the original observation-level mean without giving unequal groups equal weight accidentally.
SQL AVG Function: Averages, NULL Values and Weighted Means FAQ
Does AVG include NULL in its denominator?
No. Both the missing numerator contribution and its observation are excluded, so the average of 10, 20 and NULL is 15. To treat missing values as zero instead, average COALESCE(amount, 0), but only when zero is the correct meaning.
Can I average customer averages?
Only when equal weighting of customers is intended, or when the groups have the same number of rows. Otherwise preserve counts and weight them: SUM(customer_total) / SUM(customer_count) gives the true average per sale across all customers.
Why did my average lose decimals?
Check the input and result types. SQL Server returns an integer average for an integer column, and integer division elsewhere drops fractions. An explicit decimal cast, such as AVG(CAST(quantity AS DECIMAL(10, 2))), may be necessary in the chosen engine.
How do I round an average?
Wrap it in ROUND: ROUND(AVG(amount), 2) gives two decimal places. Round only for display, at the end, so later calculations use the full-precision value.
Is there a median function in SQL?
Not in standard aggregates everywhere. PostgreSQL and Oracle have PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount), and SQL Server offers the same as a window function. MySQL and SQLite need a ranking query or an extension. The median is often more useful than the mean when a few values are extreme.
SQL AVG Function: Averages, NULL Values and Weighted Means Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
What average is returned for paid sales only?
SQL AVG Function: Averages, NULL Values and Weighted Means Quiz
2 questions to check what you learned.
What denominator does AVG(amount) use here?
- All six sale rows, including the unknown measurement
- Five non-NULL amounts
- The four different known amount values
What is the paid-only average?
- 17, the overall known-amount average
- 11, calculated by dividing the paid total by all five known amounts
- 13.75