SQL Aggregate Functions Reference

SQL aggregate functions across MySQL, PostgreSQL, SQLite and SQL Server.

Cross-dialect SQL aggregate function reference covering COUNT, SUM, AVG, MIN, MAX, STRING_AGG, GROUP_CONCAT, ARRAY_AGG and more, with syntax, NULL handling and per-database availability. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

How do aggregate functions handle NULL?

All standard aggregates except COUNT(*) ignore NULL inputs: AVG, SUM, MIN, MAX and COUNT(col) skip NULL rows. COUNT(*) counts every row including those with NULLs. If every input is NULL, AVG/SUM/MIN/MAX return NULL rather than 0.

What aggregate functions do

An aggregate function collapses many rows into a single value per group — a sum, an average, a row count, a concatenated string. They pair with GROUP BY to produce one result row per group, or run over the whole table with no GROUP BY. This reference lists the common aggregates, their NULL behaviour, and which of MySQL, PostgreSQL, SQLite and SQL Server support each name.

How it works

Each aggregate scans the rows of a group and folds them into one value, ignoring NULL inputs (except COUNT(*)):

SELECT department,
       COUNT(*)              AS headcount,
       AVG(salary)           AS avg_salary,
       SUM(DISTINCT bonus)   AS unique_bonus_total,
       STRING_AGG(name, ', ') AS roster
FROM   employees
GROUP  BY department;

DISTINCT inside an aggregate restricts it to unique values. String aggregation is the least portable area: MySQL/SQLite spell it GROUP_CONCAT while PostgreSQL/SQL Server use STRING_AGG. The tool filters the table as you type and flags which databases provide each function.

String aggregation across dialects

Concatenating grouped strings is the most common portability trap in aggregate SQL. The four major dialects each have their own spelling:

DatabaseFunctionSeparator syntax
MySQLGROUP_CONCAT(col SEPARATOR ', ')Inside the call
SQLiteGROUP_CONCAT(col, ', ')As a second argument
PostgreSQLSTRING_AGG(col, ', ')As a second argument
SQL ServerSTRING_AGG(col, ', ')As a second argument
OracleLISTAGG(col, ', ') WITHIN GROUP (ORDER BY col)WITHIN GROUP clause

MySQL and SQLite also accept ORDER BY inside GROUP_CONCAT, while PostgreSQL’s STRING_AGG takes an ORDER BY clause in WITHIN GROUP. Getting this right matters whenever you move SQL between databases.

NULL handling — the one exception you must know

Every standard aggregate except COUNT(*) ignores NULL rows silently. This surprises developers when an expected sum or average returns NULL rather than zero: if every value in the group is NULL, the result is NULL. Wrap with COALESCE(SUM(col), 0) whenever a zero result is more appropriate than NULL.

COUNT(*) counts every row, even those where every column is NULL. COUNT(col) counts only the non-NULL values in that column. The two return different numbers whenever NULLs are present.

Tips and notes

  • COUNT(*) never returns NULL; the all-NULL group still counts its rows.
  • AVG of an empty or all-NULL set is NULL, not 0 — wrap in COALESCE if needed.
  • Mixing aggregated and non-aggregated columns requires every plain column in GROUP BY.
  • FILTER (WHERE ...) (Postgres/SQLite) is a cleaner alternative to SUM(CASE WHEN ...).
  • SUM(DISTINCT col) sums only unique values — useful for de-duplicating joins before aggregating.