3. SQL 基础回顾(二):聚合函数与分组聚合
在构建 KPI 指标看板时,我们通常不关心单条交易记录,而是关注整体趋势与汇总数值。SQL 聚合函数配合 GROUP BY 与 HAVING 子句,正是将明细数据转化为看板指标的核心工具。
3.1 五大聚合函数
聚合函数对一组值执行计算并返回单个汇总值。以下五个函数是看板开发中最常用的基础聚合操作:
| 函数 | 作用 | 适用数据类型 | 常见看板指标示例 |
|---|---|---|---|
COUNT() |
统计行数(非 NULL 值) | 任意 | 总订单数、活跃用户数 |
SUM() |
计算数值列的总和 | 数值 | 总销售额、总成本 |
AVG() |
计算数值列的平均值 | 数值 | 客单价、平均响应时长 |
MAX() |
返回最大值 | 数值、日期、字符串 | 最高单笔金额、最近登录时间 |
MIN() |
返回最小值 | 数值、日期、字符串 | 最低库存水位、最早注册日期 |
💡 避坑提示:
COUNT(*) 统计所有行,包括全 NULL 行;COUNT(column) 只统计该列非 NULL 的行数。在看板中统计“有支付记录的用户数”时,应使用 COUNT(payment_id) 而非 COUNT(*)。
基础语法示例
-- 计算订单表的核心 KPI
SELECT
COUNT(*) AS 总订单数,
SUM(amount) AS 总销售额,
AVG(amount) AS 客单价,
MAX(amount) AS 最高单笔金额,
MIN(amount) AS 最低单笔金额
FROM orders
WHERE order_date = '2025-03-01';
3.2 GROUP BY:按维度分组聚合
看板中的指标通常需要按维度(如时间、地区、产品类别)拆分展示。GROUP BY 子句将查询结果按一个或多个列分组,然后对每个分组独立执行聚合函数。
📌 执行顺序:
WHERE → GROUP BY → 聚合函数 → HAVING → ORDER BY。先过滤明细行,再分组聚合。
按单维度分组
-- 按产品类别统计销售额与订单数
SELECT
category AS 产品类别,
COUNT(*) AS 订单数,
SUM(amount) AS 销售额,
AVG(amount) AS 平均单价
FROM orders
WHERE order_date BETWEEN '2025-01-01' AND '2025-01-31'
GROUP BY category
ORDER BY 销售额 DESC;
按多维度分组
-- 按年-月 + 地区统计 KPI
SELECT
YEAR(order_date) AS 年份,
MONTH(order_date) AS 月份,
region AS 地区,
COUNT(*) AS 订单数,
SUM(amount) AS 销售额
FROM orders
GROUP BY YEAR(order_date), MONTH(order_date), region
ORDER BY 年份, 月份, 地区;
⚠️ 常见错误:
SELECT 中出现的非聚合列必须全部出现在 GROUP BY 中。例如 SELECT category, region, SUM(amount) ... GROUP BY category 会报错,因为 region 未在分组中。
3.3 HAVING:对聚合结果进行过滤
WHERE 子句无法过滤聚合函数的结果(因为聚合发生在 WHERE 之后)。HAVING 专门用于对分组后的聚合结果设置条件,是看板中筛选“高价值分组”的关键工具。
| 过滤时机 | 子句 | 能否使用聚合函数 | 典型场景 |
|---|---|---|---|
| 分组前 | WHERE |
❌ 不能 | 过滤时间范围、状态 |
| 分组后 | HAVING |
✅ 可以 | 筛选销售额 > 10000 的品类 |
HAVING 使用示例
-- 找出月销售额超过 50000 且订单数超过 100 的产品类别
SELECT
category AS 产品类别,
COUNT(*) AS 订单数,
SUM(amount) AS 月销售额
FROM orders
WHERE order_date BETWEEN '2025-01-01' AND '2025-01-31'
GROUP BY category
HAVING SUM(amount) > 50000
AND COUNT(*) > 100
ORDER BY 月销售额 DESC;
💡 性能建议: 能用
WHERE 过滤的原始行条件,绝不要放到 HAVING 中。先 WHERE 减少数据量,再 GROUP BY 聚合,最后 HAVING 过滤分组,这是看板查询的黄金法则。
3.4 聚合流程可视化
下图展示了从原始明细数据到看板 KPI 指标的完整聚合链路:
3.5 综合案例:构建看板数据查询
假设我们需要为电商看板提供“月度品类销售分析”数据,要求展示每个品类在 2025 年第一季度的月销售额、订单数、客单价,并只保留月销售额超过 30000 的品类记录。
SELECT
category AS 品类,
DATE_FORMAT(order_date, '%Y-%m') AS 月份,
COUNT(*) AS 订单数,
SUM(amount) AS 月销售额,
ROUND(AVG(amount), 2) AS 客单价
FROM orders
WHERE order_date BETWEEN '2025-01-01' AND '2025-03-31'
AND status = 'completed'
GROUP BY category, DATE_FORMAT(order_date, '%Y-%m')
HAVING SUM(amount) > 30000
ORDER BY 月份, 月销售额 DESC;
📌 看板对接提示: 上述查询结果可直接作为 ECharts 柱状图或折线图的数据源。将
月份 映射到 X 轴,月销售额 映射到 Y 轴,品类 作为系列分组,即可快速生成多品类趋势对比图。
3.6 聚合函数与 NULL 值的处理
| 聚合函数 | NULL 处理方式 | 看板影响 |
|---|---|---|
COUNT(column) |
忽略 NULL 行 | 统计非空值数量,避免虚高 |
SUM() |
忽略 NULL,视作 0 | 总和不受 NULL 影响 |
AVG() |
忽略 NULL,分母不含 NULL 行 | 平均值可能偏高,需注意 |
MAX() / MIN() |
忽略 NULL | 极值不受 NULL 干扰 |
⚠️ 注意: 如果某列全为 NULL,
SUM() 返回 NULL 而非 0。在看板中建议使用 COALESCE(SUM(column), 0) 将 NULL 转为 0,避免图表数据断点。
3.7 本章小结
- COUNT / SUM / AVG / MAX / MIN 是看板指标计算的五大基础函数,各自有明确的适用场景与 NULL 处理规则。
- GROUP BY 实现按维度分组聚合,是看板中“按时间/地区/品类”拆分的核心语法。
- HAVING 专用于过滤聚合后的分组结果,与 WHERE 形成互补。
- 执行顺序 WHERE → GROUP BY → 聚合 → HAVING → ORDER BY 是编写高效看板查询的底层逻辑。