核心聚合函数
聚合函数对一组值进行计算,并返回一个单一的值,它们通常与 GROUP BY 子句一起使用。

| 函数 | 描述 | 示例 |
|---|---|---|
COUNT() |
计算行的数量。 | COUNT(*), COUNT(列名) |
SUM() |
计算数值列的总和。 | SUM(价格) |
AVG() |
计算数值列的平均值。 | AVG(成绩) |
MAX() |
返回列中的最大值。 | MAX(年龄) |
MIN() |
返回列中的最小值。 | MIN(创建时间) |
重要提示:
COUNT(*): 计算所有行的数量,包括NULL值。COUNT(列名): 只计算指定列中非 NULL 值的数量。
GROUP BY 子句
GROUP BY 子句将查询结果按照一个或多个列进行分组,通常与聚合函数结合使用,对每个分组分别进行统计。
语法结构:
SELECT
column_name(s),
aggregate_function(column_name)
FROM
table_name
WHERE
condition
GROUP BY
column_name(s);
示例数据
我们以一个 orders (订单) 表为例:

CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
product_name VARCHAR(100),
amount DECIMAL(10, 2),
order_date DATE
);
INSERT INTO orders (id, customer_id, product_name, amount, order_date) VALUES
(1, 101, '笔记本电脑', 5999.00, '2025-10-01'),
(2, 102, '无线鼠标', 99.00, '2025-10-01'),
(3, 101, '机械键盘', 399.00, '2025-10-02'),
(4, 103, '显示器', 1999.00, '2025-10-03'),
(5, 102, '笔记本电脑', 5999.00, '2025-10-04'),
(6, 101, '无线鼠标', 89.00, '2025-10-05');
示例 1:按客户分组,统计每个客户的订单总金额和订单数量
SELECT
customer_id,
SUM(amount) AS total_amount,
COUNT(id) AS order_count
FROM
orders
GROUP BY
customer_id;
结果: | customer_id | total_amount | order_count | | :--- | :--- | :--- | | 101 | 6487.00 | 3 | | 102 | 6098.00 | 2 | | 103 | 1999.00 | 1 |
示例 2:按产品名称分组,统计每个产品的销售总量
SELECT
product_name,
SUM(amount) AS total_sales
FROM
orders
GROUP BY
product_name;
结果: | product_name | total_sales | | :--- | :--- | | 笔记本电脑 | 11998.00 | | 无线鼠标 | 188.00 | | 机械键盘 | 399.00 | | 显示器 | 1999.00 |
HAVING 子句
HAVING 子句用于对分组后的结果进行筛选,它与 WHERE 的区别在于:
WHERE: 在分组之前过滤行。HAVING: 在分组之后过滤组。
语法结构:

SELECT
column_name(s),
aggregate_function(column_name)
FROM
table_name
WHERE
condition
GROUP BY
column_name(s)
HAVING
condition;
示例:统计每个客户的订单总金额,并只显示总金额超过 5000 的客户
SELECT
customer_id,
SUM(amount) AS total_amount
FROM
orders
GROUP BY
customer_id
HAVING
total_amount > 5000;
结果: | customer_id | total_amount | | :--- | :--- | | 101 | 6487.00 | | 102 | 6098.00 |
多列分组
GROUP BY 可以按多个列进行分组,这会创建更细致的分组层级。
示例:按客户和产品名称分组,统计每个客户购买每种产品的数量和总金额
SELECT
customer_id,
product_name,
COUNT(id) AS purchase_times,
SUM(amount) AS total_spent
FROM
orders
GROUP BY
customer_id, product_name;
结果: | customer_id | product_name | purchase_times | total_spent | | :--- | :--- | :--- | :--- | | 101 | 笔记本电脑 | 1 | 5999.00 | | 101 | 机械键盘 | 1 | 399.00 | | 101 | 无线鼠标 | 2 | 188.00 | | 102 | 笔记本电脑 | 1 | 5999.00 | | 102 | 无线鼠标 | 1 | 99.00 | | 103 | 显示器 | 1 | 1999.00 |
WITH ROLLUP (超级聚合)
WITH ROLLUP 是 GROUP BY 的一个扩展,它会在常规分组的基础上,再添加一行“小计”和“总计”行。
示例:按客户分组统计订单总金额,并使用 WITH ROLLUP 添加总计
SELECT
customer_id,
SUM(amount) AS total_amount
FROM
orders
GROUP BY
customer_id WITH ROLLUP;
结果: | customer_id | total_amount | | :--- | :--- | | 101 | 6487.00 | | 102 | 6098.00 | | 103 | 1999.00 | | NULL | 14584.00 | <-- 这是所有客户的总金额 |
注意: 当分组列为 NULL 时,通常表示“总计”或“小计”。
窗口函数 (MySQL 8.0+)
窗口函数是比传统聚合函数更强大的工具,它们可以在不减少行数的情况下进行计算,每个窗口函数都有一个 OVER() 子句来定义其计算窗口。
常用窗口函数:
SUM(),AVG(),COUNT(),MAX(),MIN(): 聚合窗口函数。ROW_NUMBER(): 为窗口中的每一行分配一个唯一的序号。RANK(): 为窗口中的每一行分配一个排名,如果有并列,则排名会跳跃。DENSE_RANK(): 与RANK()类似,但并列不会导致排名跳跃。LAG(): 访问之前行的数据。LEAD(): 访问之后行的数据。
示例 1:计算每个客户的订单金额,并显示每个客户的总金额(不减少行数)
SELECT
id,
customer_id,
amount,
SUM(amount) OVER (PARTITION BY customer_id) AS customer_total_amount
FROM
orders;
结果: | id | customer_id | amount | customer_total_amount | | :--- | :--- | :--- | :--- | | 1 | 101 | 5999.00 | 6487.00 | | 3 | 101 | 399.00 | 6487.00 | | 6 | 101 | 89.00 | 6487.00 | | 2 | 102 | 99.00 | 6098.00 | | 5 | 102 | 5999.00 | 6098.00 | | 4 | 103 | 1999.00 | 1999.00 |
示例 2:为每个客户的订单按金额从高到低进行排名
SELECT
id,
customer_id,
amount,
RANK() OVER (PARTITION BY customer_id ORDER BY amount DESC) as rank_within_customer
FROM
orders;
结果: | id | customer_id | amount | rank_within_customer | | :--- | :--- | :--- | :--- | | 1 | 101 | 5999.00 | 1 | | 3 | 101 | 399.00 | 2 | | 6 | 101 | 89.00 | 3 | | 5 | 102 | 5999.00 | 1 | | 2 | 102 | 99.00 | 2 | | 4 | 103 | 1999.00 | 1 |
其他实用统计命令
COUNT(DISTINCT column_name)
计算列中不同值的数量。
示例: 统计有多少个不同的客户下了订单。
SELECT COUNT(DISTINCT customer_id) AS unique_customers FROM orders;
结果: | unique_customers | | :--- | | 3 |
GROUP_CONCAT()
将一个组的值连接成一个字符串。
示例: 列出每个客户购买的所有产品名称。
SELECT
customer_id,
GROUP_CONCAT(product_name SEPARATOR ', ') AS purchased_products
FROM
orders
GROUP BY
customer_id;
结果: | customer_id | purchased_products | | :--- | :--- | | 101 | 笔记本电脑, 机械键盘, 无线鼠标 | | 102 | 无线鼠标, 笔记本电脑 | | 103 | 显示器 |
| 功能 | 关键字/函数 | 说明 |
|---|---|---|
| 基础统计 | COUNT(), SUM(), AVG(), MAX(), MIN() |
对一组数据进行单值计算。 |
| 分组统计 | GROUP BY |
将数据分组,以便对每个组应用聚合函数。 |
| 分组后筛选 | HAVING |
在 GROUP BY 之后,对分组的结果进行过滤。 |
| 多维度统计 | 多列 GROUP BY |
按多个列进行更细粒度的分组。 |
| 超级聚合 | WITH ROLLUP |
在分组结果上增加小计和总计行。 |
| 高级分析 | 窗口函数 (OVER()) |
在不减少行数的情况下进行复杂的排名和聚合计算。 |
| 去重统计 | COUNT(DISTINCT ...) |
计算唯一值的数量。 |
| 字符串聚合 | GROUP_CONCAT() |
将分组内的值合并成一个字符串。 |
掌握这些命令,你就可以应对绝大多数MySQL数据统计场景了,从简单的求和计数到复杂的排名分析,都能游刃有余。
