AVG() Function in MySQL
Introduction
Average calculations provide essential statistical insights across datasets.
AVG() function computes arithmetic mean of non-NULL numeric values.
It is widely used for:
- Performance metrics
- Statistical analysis
- Business intelligence reports
What is AVG() Function
AVG() returns sum of non-NULL values divided by count of non-NULL values.
Automatically ignores NULL values in calculations.
Basic Syntax
sql
SELECT AVG(column_name) FROM table_name;
Example
sql
SELECT AVG(marks) as average_marks FROM Students;
Returns average of all non-NULL marks.
AVG with GROUP BY
Categorize averages.
sql
SELECT city, AVG(marks) as city_average
FROM Students
GROUP BY city;
AVG with WHERE
Conditional averages.
sql
SELECT AVG(marks) FROM Students
WHERE status = 'Active';
AVG with Multiple Aggregates
Combine statistics.
sql
SELECT city,
AVG(marks) as avg_marks,
COUNT(*) as student_count,
MIN(marks) as lowest,
MAX(marks) as highest
FROM Students
GROUP BY city;
AVG with ORDER BY
Sort by averages.
sql
SELECT department, ROUND(AVG(marks), 2) as avg_marks
FROM Students
GROUP BY department
ORDER BY avg_marks DESC;
AVG(DISTINCT)
Average of unique values only.
sql
SELECT AVG(DISTINCT marks) as unique_avg
FROM Students;
AVG with JOIN
Cross-table averages.
sql
SELECT c.course_name, AVG(s.marks) as course_avg
FROM Students s
JOIN Courses c ON s.course_id = c.id
GROUP BY c.id, c.course_name;
AVG with HAVING
Filter grouped averages.
sql
SELECT city, AVG(marks) as avg_marks
FROM Students
GROUP BY city
HAVING AVG(marks) > 75;
Conditional AVG with CASE
Weighted or filtered averages.
sql
SELECT city,
AVG(CASE WHEN status = 'Active' THEN marks ELSE NULL END) as active_avg,
AVG(CASE WHEN marks > 0 THEN marks ELSE NULL END) as valid_avg
FROM Students
GROUP BY city;
AVG with Subquery
Compare against overall average.
sql
SELECT name, marks
FROM Students
WHERE marks > (SELECT AVG(marks) FROM Students WHERE marks IS NOT NULL);
Handling Edge Cases
NULL and zero handling.
sql
SELECT
COALESCE(AVG(marks), 0) as safe_avg,
AVG(CASE WHEN marks > 0 THEN marks END) as positive_avg
FROM Students;
Execution Order with AVG
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
Performance Considerations
- AVG(column) scans for NULLs
- AVG(DISTINCT) very slow (deduplication)
- Index GROUP BY columns
- Large tables: consider sampling
Important Notes
- Ignores NULL values automatically
- Empty set returns NULL (use COALESCE)
- Works only on numeric columns
- AVG(DISTINCT) removes duplicates first
- ROUND(AVG(), 2) for display formatting
Example Scenario
Complete course performance analysis:
sql
SELECT
c.course_name,
COUNT(s.id) as total_students,
ROUND(AVG(s.marks), 2) as average_marks,
COUNT(CASE WHEN s.marks >= 90 THEN 1 END) as a_grade_count,
ROUND(AVG(CASE WHEN s.status = 'Active' THEN s.marks END), 2) as active_avg
FROM Courses c
LEFT JOIN Students s ON c.id = s.course_id
GROUP BY c.id, c.course_name
HAVING AVG(s.marks) > 70
ORDER BY average_marks DESC;
Common Mistakes
- AVG on non-numeric columns
- Surprised by NULL exclusion
- Performance hit from AVG(DISTINCT)
- WHERE vs HAVING confusion
- Forgetting COALESCE for NULL results
Key Points to Remember
- AVG computes mean of non-NULL values
- GROUP BY + AVG = category averages
- Automatically ignores NULLs
- AVG(DISTINCT) for unique value averages
- HAVING AVG() > X filters groups
- COALESCE(AVG(), 0) handles empty results