Administrator
Administrator
发布于 2026-10-27 / 0 阅读
0
0

数据库入门到初级(10):聚合与分组:用 SQL 做简单统计

数据库入门到初级 · 第 10/22 篇。实验口径:MySQL 8.4、InnoDB、utf8mb4。案例:小型商城。

“小林一共消费了多少?”看起来只是把金额相加,但如果把待支付、已取消订单也算进去,SQL 即使运行成功,业务答案仍然可能错。本篇先把统计范围说清楚,再学习聚合语法。

1. 聚合函数把多行变成统计值

SELECT COUNT(*) AS order_count,
       SUM(total_amount) AS amount_sum,
       AVG(total_amount) AS amount_avg,
       MIN(total_amount) AS amount_min,
       MAX(total_amount) AS amount_max
FROM orders
WHERE status = 'paid';

样例中已支付订单为 288 和 129,因此数量 2、总额 417、平均 208.5、最小 129、最大 288。小数展示位数可能随客户端而不同。

本教程将 paid 订单金额称为“已支付订单金额”,它没有实现退款、优惠分摊和多币种,不能直接当作真实企业财务收入。

2. GROUP BY:每组分别计算

SELECT user_id,
       COUNT(*) AS paid_order_count,
       SUM(total_amount) AS paid_amount
FROM orders
WHERE status = 'paid'
GROUP BY user_id
ORDER BY user_id;

结果只有用户 1,一共 2 单、417 元。用户 2 没有已支付订单,用户 3 没有订单,都不会出现在这个结果里。如果需要展示所有用户,即使消费为 0 也保留,就要结合下一篇的左连接。

分组统计的逻辑步骤

图表示理解查询含义的逻辑顺序,不是数据库承诺的物理执行顺序。优化器可以在保证结果含义的前提下调整访问策略。

3. WHERE 与 HAVING 分别过滤什么

SELECT user_id, SUM(total_amount) AS paid_amount
FROM orders
WHERE status = 'paid'
GROUP BY user_id
HAVING SUM(total_amount) > 300;

WHERE 在分组前排除不需要的原始记录;HAVING 检查分组后的统计结果。上面先只保留已支付订单,再找总额超过 300 的用户。

不能把同层聚合条件直接写成 WHERE SUM(total_amount) > 300。也不要为了“能执行”而把所有过滤条件都塞到 HAVING,那会让意图难读,也可能增加无谓处理。

4. NULL 会怎样影响统计

COUNT(*) 计算行数,COUNT(phone) 只统计 phone 非 NULL 的行。SUM 和 AVG 通常忽略空值;如果没有符合条件的记录,SUM 返回 NULL,而 COUNT(*) 返回 0。

SELECT COUNT(*) AS n,
       COALESCE(SUM(total_amount), 0) AS paid_amount
FROM orders
WHERE user_id = 3 AND status = 'paid';

得到 0 单、0 元。这里把“没有已支付订单的合计”展示为 0 是明确的业务选择;不要在所有场景里都机械地把未知数据转换成 0。

5. 分组后还能随便选名称吗

SELECT status, COUNT(*) AS n
FROM orders
GROUP BY status
ORDER BY status;

这条合法,因为每组由状态定义。若额外选取某张订单的 id,一组可能有多个编号,数据库就不知道该显示哪一个。不要通过关闭 ONLY_FULL_GROUP_BY 掩盖分组含义不清的问题。

初学时可以遵循一个易检查的规则:选择列表里的字段,要么参与分组,要么在聚合函数里。MySQL 还能识别部分函数依赖情形,但不必一开始就依赖这些扩展。

练习与答案

练习:统计每种订单状态的订单数量与金额。

SELECT status, COUNT(*) AS n, SUM(total_amount) AS amount
FROM orders
GROUP BY status
ORDER BY status;

应得到 cancelled: 1, 29、paid: 2, 417、pending: 1, 178。最后检查:分组数量合计为 4,金额合计为 624。总量核对是发现漏数或重复统计的好习惯。


上一篇:第 09 篇 · 系列目录 · 下一篇:第 11 篇


评论