Chapter 26: PostgreSQL AVG Function

PostgreSQL: the AVG() function ☕📊

You’ve already learned SELECT, GROUP BY, operators, and built small demo tables. Today we focus on how to calculate averages properly — because AVG() looks simple, but people make very common mistakes with it (especially with grouping, data types, NULLs, and rounding).

1. What does AVG() actually do? (Honest teacher explanation)

AVG() is an aggregate function that computes the arithmetic mean (average) of a set of numeric values.

Formula inside PostgreSQL:

text

Important points right now in PostgreSQL 18 (2026 reality):

  • Ignores NULL values completely (does not count them in the denominator)
  • Input types: works on smallint, integer, bigint, real, double precision, numeric, interval
  • Return type:
    • numeric when input is integer types
    • double precision when input is floating-point (real or double precision)
    • same as input for numeric or interval
  • Very precise with numeric type (no floating-point rounding errors)
  • Can be used in SELECT, HAVING, subqueries, window functions, etc.

Official short description (from current PostgreSQL docs):

avg(expression) — the average (arithmetic mean) of all input values

2. Basic syntax patterns (what you’ll type 90% of the time)

SQL

3. Real examples – using our students table (from earlier classes)

Assume this students table (some rows for illustration):

id first_name gpa enrollment_year fees_paid
1 Aarav 8.95 2025 TRUE
2 Priya 9.60 2024 FALSE
3 Rahul 7.85 2025 FALSE
4 Sneha 9.20 2025 TRUE
5 Meera 10.00 2025 TRUE
6 Kiran NULL 2023 FALSE

Example 1: Overall class average GPA

SQL

Result (approx):

text

→ Notice: Kiran’s NULL GPA is ignored — denominator = 5, not 6

Example 2: Nice rounded display (most common real usage)

SQL

Result:

text

→ ROUND() or ::NUMERIC(precision,scale) — choose whichever you prefer

Example 3: Average GPA per enrollment year (GROUP BY)

SQL

Result (example):

text

→ 2023 has NULL GPA → AVG(gpa) returns NULL for that group

Example 4: Average only for active students + HAVING filter

SQL

→ Only years where average GPA is 9.0 or higher appear

Example 5: Average with JOIN (realistic bookstore style)

Imagine our order_items table:

SQL

→ Shows average price per book title (useful if prices change over time)

4. Common traps & best practices (from real student & production experience)

Mistake / Question What happens / Wrong result Correct way / Explanation
AVG(column) on table with many NULLs Average looks higher than expected NULLs are ignored — correct behavior
Want to treat NULL as 0 AVG(COALESCE(gpa, 0))
Floating point weirdness 3.3333333333333335 instead of nice number Cast: AVG(…)::NUMERIC(10,2) or ROUND(AVG(…), 2)
GROUP BY without aggregate on other cols ERROR: column must appear in GROUP BY or aggregate Add to GROUP BY or wrap in aggregate
Average of intervals Works! (avg duration) AVG(end_time – start_time) → interval result
Very large dataset performance Slow without index on GROUP BY columns Index the grouping columns

5. Quick summary cheat-sheet (keep this in your notes)

  • AVG() → arithmetic mean, ignores NULLs
  • Return type → numeric or double precision mostly
  • Best display: ROUND(AVG(col), 2) or ::NUMERIC(p,s)
  • With GROUP BY → one average per group
  • With HAVING → filter groups after averaging
  • With COALESCE() → treat NULL as 0 if needed
  • Works great with JOIN, subqueries, CTEs, window functions

Your mini practice right now (try in your database)

  1. Calculate overall average GPA
  2. Average GPA per enrollment year (with rounded display)
  3. Average GPA only for students with GPA IS NOT NULL and fees_paid = TRUE
  4. Add a dummy salary column to students → calculate average salary per city (if you have city column)

Next class?

Tell me:

  • Want SUM(), COUNT(), MIN/MAX in detail (other aggregates)?
  • AVG() inside window functions (running average, moving average)?
  • How AVG() behaves with money / interval / weighted average?
  • Or deeper into GROUP BY + HAVING + WHERE combinations?

Your teacher is right here — what’s next? 🚀

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *