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 指标的完整聚合链路:

SQL 聚合流程:从明细到看板 KPI 原始明细表 orders(百万行) WHERE 行过滤 时间 / 状态 / 地区 GROUP BY 分组 按类别 / 月份 / 地区 聚合函数计算 SUM / COUNT / AVG HAVING 分组过滤 销售额 > 阈值 看板 KPI 指标 ECharts 图表数据源 执行顺序说明 FROM → WHERE → GROUP BY → 聚合 → HAVING → ORDER BY

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 是编写高效看板查询的底层逻辑。