聚合函数:COUNT、SUM、AVG、MIN、MAX
什么是聚合函数
聚合函数(Aggregate Function)对一组行进行计算,返回单个值。
示例:从第一章的 users 表开始
-- 查看数据
SELECT * FROM users;结果(5 行):
id | name | email | age
----+---------+---------------------+-----
1 | Alice | alice@example.com | 30
2 | Bob | bob@example.com | 25
3 | Charlie | charlie@example.com | 35
4 | Diana | diana@example.com | 28
5 | Eve | eve@example.com |使用聚合函数:
-- 计算总行数
SELECT COUNT(*) FROM users;结果(1 行):
count
-------
5聚合函数将 5 行数据合并成 1 个结果。
COUNT:计数
COUNT(*) vs COUNT(column)
COUNT(*):计数所有行,包括 NULL
SELECT COUNT(*) AS total_users FROM users;结果:
total_users
-------------
5COUNT(column):只计数非 NULL 的行
SELECT COUNT(age) AS users_with_age FROM users;结果:
users_with_age
----------------
4Eve 的年龄是 NULL,所以没有被计入。
COUNT(DISTINCT column):去重计数
-- 创建订单表用于演示
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_name VARCHAR(50),
product VARCHAR(50),
amount DECIMAL(10, 2),
order_date DATE
);
INSERT INTO orders (customer_name, product, amount, order_date) VALUES
('Alice', 'Laptop', 1200.00, '2026-01-15'),
('Bob', 'Mouse', 25.00, '2026-01-16'),
('Alice', 'Keyboard', 80.00, '2026-01-17'),
('Charlie', 'Monitor', 300.00, '2026-01-18'),
('Bob', 'Headphones', 50.00, '2026-01-19'),
('Alice', 'USB Cable', 10.00, '2026-01-20');计数订单和客户:
-- 总订单数
SELECT COUNT(*) AS total_orders FROM orders;
-- 结果:6
-- 不同客户的数量
SELECT COUNT(DISTINCT customer_name) AS unique_customers FROM orders;
-- 结果:3SUM:求和
SUM 计算数值列的总和,忽略 NULL。
-- 总销售额
SELECT SUM(amount) AS total_sales FROM orders;结果:
total_sales
-------------
1665.00计算:1200 + 25 + 80 + 300 + 50 + 10 = 1665
SUM 忽略 NULL
-- 假设有 NULL 值
INSERT INTO orders (customer_name, product, amount, order_date) VALUES
('Diana', 'Cable', NULL, '2026-01-21');
SELECT SUM(amount) AS total_sales FROM orders;结果仍然是 1665.00(NULL 被忽略)。
SUM 与非数值列
-- 错误:不能对字符串求和
SELECT SUM(customer_name) FROM orders;错误信息:
ERROR: function sum(character varying) does not existAVG:平均值
AVG 计算数值列的平均值,忽略 NULL。
-- 平均订单金额
SELECT AVG(amount) AS average_order FROM orders;结果:
average_order
---------------
277.500000计算:1665 / 6 = 277.5
注意精度
PostgreSQL 和 MySQL 返回的精度可能不同:
-- 四舍五入到两位小数
SELECT ROUND(AVG(amount), 2) AS average_order FROM orders;结果:
average_order
---------------
277.50AVG 与 NULL
-- 用户的平均年龄(Eve 的 NULL 被忽略)
SELECT AVG(age) AS average_age FROM users;结果:
average_age
-------------
29.500000计算:(30 + 25 + 35 + 28) / 4 = 29.5
如果要把 NULL 当作 0:
SELECT AVG(COALESCE(age, 0)) AS average_age_with_zero FROM users;结果:
average_age_with_zero
-----------------------
23.600000计算:(30 + 25 + 35 + 28 + 0) / 5 = 23.6
MIN 和 MAX:最小值和最大值
MIN 和 MAX 可以用于数值、字符串、日期:
数值
-- 最低和最高年龄
SELECT
MIN(age) AS youngest,
MAX(age) AS oldest
FROM users
WHERE age IS NOT NULL;结果:
youngest | oldest
----------+--------
25 | 35字符串
字符串按字典顺序比较:
-- 第一个和最后一个客户名(字母顺序)
SELECT
MIN(customer_name) AS first_name,
MAX(customer_name) AS last_name
FROM orders;结果:
first_name | last_name
------------+-----------
Alice | Diana日期
-- 最早和最晚的订单日期
SELECT
MIN(order_date) AS first_order,
MAX(order_date) AS last_order
FROM orders;结果:
first_order | last_order
-------------+------------
2026-01-15 | 2026-01-21组合多个聚合函数
可以在一个 SELECT 中使用多个聚合函数:
SELECT
COUNT(*) AS total_orders,
COUNT(DISTINCT customer_name) AS unique_customers,
SUM(amount) AS total_sales,
AVG(amount) AS average_order,
MIN(amount) AS smallest_order,
MAX(amount) AS largest_order
FROM orders
WHERE amount IS NOT NULL;结果:
total_orders | unique_customers | total_sales | average_order | smallest_order | largest_order
--------------+------------------+-------------+---------------+----------------+---------------
6 | 3 | 1665.00 | 277.500000 | 10.00 | 1200.00聚合函数与 WHERE
WHERE 在聚合前过滤数据:
-- 2026 年 1 月 17 日之后的订单统计
SELECT
COUNT(*) AS recent_orders,
SUM(amount) AS recent_sales
FROM orders
WHERE order_date > '2026-01-17';结果:
recent_orders | recent_sales
---------------+--------------
4 | 360.00聚合函数的限制
不能在 WHERE 中使用聚合函数
-- 错误:WHERE 不能用聚合函数
SELECT * FROM orders WHERE amount > AVG(amount);错误信息:
ERROR: aggregate functions are not allowed in WHERE正确做法(使用子查询,后续章节详细讲解):
SELECT * FROM orders
WHERE amount > (SELECT AVG(amount) FROM orders WHERE amount IS NOT NULL);不能混用聚合和非聚合列
-- 错误:name 是多行,COUNT(*) 是一行
SELECT name, COUNT(*) FROM users;错误信息(PostgreSQL):
ERROR: column "users.name" must appear in the GROUP BY clause or be used in an aggregate function正确做法:要么只用聚合,要么用 GROUP BY(下一节)。
常用聚合函数速查
| 函数 | 作用 | NULL 处理 |
|---|---|---|
COUNT(*) | 计数所有行 | 包括 NULL |
COUNT(column) | 计数非 NULL 行 | 忽略 NULL |
COUNT(DISTINCT column) | 去重计数 | 忽略 NULL |
SUM(column) | 求和 | 忽略 NULL |
AVG(column) | 平均值 | 忽略 NULL |
MIN(column) | 最小值 | 忽略 NULL |
MAX(column) | 最大值 | 忽略 NULL |
练习
使用 orders 表完成以下练习:
基本计数:查询 orders 表的总行数。
去重计数:查询有多少个不同的产品。
求和:计算所有订单的总金额(排除 NULL)。
平均值:计算平均订单金额,保留两位小数。
最值:查询最小和最大订单金额。
组合统计:一次查询返回:总订单数、不同客户数、总销售额、平均订单金额。
条件聚合:计算金额大于 100 的订单总数和总金额。
NULL 处理:分别计算
COUNT(*)和COUNT(amount)的差异(提示:插入一行 amount 为 NULL 的数据)。
完成练习后,打开本章答案页核对。
下一步
学会了聚合函数。下一节学习 GROUP BY:如何按列分组,对每组分别进行聚合统计。