2.20 基础聚合函数(COUNT、SUM、AVG、MAX、MIN)
在电商数据分析中,你几乎每天都要用到聚合函数:
-
统计总订单数(
COUNT)。 -
计算总销售额(
SUM)。 -
求平均客单价(
AVG)。 -
找最高/最低金额(
MAX/MIN)。
这一章我会带你彻底搞懂五个最常用的聚合函数:COUNT、SUM、AVG、MAX、MIN。学完之后,你能独立完成电商核心经营指标的一站式统计。
学习前准备:
-
已完成MySQL安装(参考系列前几章)
-
已安装DBeaver或Navicat
-
准备一个练习数据库,比如
agg_demo
学习前环境准备
步骤1:确保MySQL服务已启动。
步骤2:创建练习数据库和表,并插入示例数据。
sql
CREATE DATABASE agg_demo
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE agg_demo;
-- 订单表
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
shop_name VARCHAR(50) NOT NULL,
product_name VARCHAR(100),
amount DECIMAL(10,2) NOT NULL,
quantity INT NOT NULL DEFAULT 1,
order_status VARCHAR(20) NOT NULL,
create_time DATETIME NOT NULL
);
INSERT INTO orders (user_id, shop_name, product_name, amount, quantity, order_status, create_time) VALUES
(1001, '女装旗舰店', '碎花连衣裙', 299.00, 2, '已支付', '2025-06-01 10:00:00'),
(1002, '女装旗舰店', '纯棉T恤', 189.00, 3, '已取消', '2025-06-01 11:00:00'),
(1003, '男装专营店', '牛仔裤', 599.00, 1, '已支付', '2025-06-02 09:30:00'),
(1001, '女装旗舰店', '雪纺衫', 399.00, 1, '已支付', '2025-06-03 14:20:00'),
(1004, '童装店', '儿童T恤', 99.00, 5, '已完成', '2025-06-03 16:00:00'),
(1005, '女装旗舰店', '真丝连衣裙', 1299.00, 1, '已支付', '2025-06-04 08:30:00'),
(1002, '男装专营店', '休闲短裤', 89.00, 2, '已取消', '2025-06-04 10:00:00'),
(1006, '女装旗舰店', '基础打底衫', 89.00, 10, '已支付', '2025-06-05 09:00:00'),
(1007, '男装专营店', 'Polo衫', 259.00, 1, '已支付', '2025-06-05 14:00:00');
聚合函数基础认知
聚合函数对一组值执行计算,返回单个结果。它们通常与GROUP BY配合使用,也可以单独用于全表统计。
常用聚合函数:
| 函数 | 作用 | 电商示例 |
|---|---|---|
COUNT() |
计数 | 订单数、用户数 |
SUM() |
求和 | GMV、销量 |
AVG() |
平均值 | 客单价、件单价 |
MAX() |
最大值 | 最高订单金额 |
MIN() |
最小值 | 最低商品售价 |
执行逻辑 :聚合函数会在WHERE筛选之后、GROUP BY分组之后对每组进行计算。 |
我的踩坑经历 :第一次用
COUNT(*)时,我以为COUNT(column)和COUNT(*)一样,后来发现COUNT(column)会忽略NULL值,导致计数偏少。从此我根据需求选择正确的形式。
COUNT函数详解(计数)
4.1 基础语法
sql
COUNT(*) -- 统计所有行(包括NULL)
COUNT(列名) -- 统计该列非NULL的行数
COUNT(DISTINCT 列名) -- 统计去重后的数量
4.2 电商实操案例
案例一:统计总订单数
sql
SELECT COUNT(*) AS total_orders FROM orders;
预期结果:9。
案例二:统计已支付订单数
sql
SELECT COUNT(*) AS paid_orders FROM orders WHERE order_status = '已支付';
预期结果:6(ORD001、ORD003、ORD004、ORD006、ORD008、ORD009)。
案例三:统计有商品名称的订单数(排除NULL)
假设没有NULL,演示用法。
sql
SELECT COUNT(product_name) AS has_product_name FROM orders;
案例四:统计独立用户数(去重)
sql
SELECT COUNT(DISTINCT user_id) AS unique_users FROM orders;
预期结果:7(1001,1002,1003,1004,1005,1006,1007)。
4.3 分步操作
-
确定要统计的对象(所有行、某列非空、去重)。
-
加上
WHERE条件(如果需要)。 -
执行并验证。
避坑提醒:
-
COUNT(*)和COUNT(1)性能几乎相同,推荐用COUNT(*)。 -
COUNT(column)会忽略NULL,如果不确定是否有NULL,用COUNT(*)更安全。
实操避坑提醒 :统计用户数时,必须用
COUNT(DISTINCT user_id),否则同一用户多单会被重复计数。
SUM函数详解(求和)
5.1 基础语法
sql
SUM(列名) -- 对数值列求和,自动忽略NULL
5.2 电商实操案例
案例一:计算全店GMV(已支付订单总金额)
sql
SELECT SUM(amount) AS gmv FROM orders WHERE order_status = '已支付';
预期结果:299+599+399+1299+89+259 = 2944? 计算:299+599=898,+399=1297,+1299=2596,+89=2685,+259=2944。正确。
案例二:计算女装旗舰店的总销量(数量)
sql
SELECT SUM(quantity) AS total_quantity FROM orders WHERE shop_name = '女装旗舰店';
预期结果 :2+3+1+1+10 = 17? 注意ORD002是已取消但数量也计入?通常只计有效订单,需要加order_status条件。
sql
SELECT SUM(quantity) AS total_quantity FROM orders WHERE shop_name = '女装旗舰店' AND order_status = '已支付';
预期结果:ORD001(2), ORD004(1), ORD006(1), ORD008(10) = 14。
案例三:计算退款总金额(假设退款订单状态为"已取消")
sql
SELECT SUM(amount) AS refund_amount FROM orders WHERE order_status = '已取消';
预期结果:189+89=278。
5.3 分步操作
-
筛选有效订单(
WHERE)。 -
对需要求和的列使用
SUM。 -
执行验证。
避坑提醒:
-
SUM自动忽略NULL,但不会忽略字符串。确保列是数值类型。 -
对金额列求和时,注意单位一致(如都是元)。
我的踩坑经历 :我写过
SUM(amount),结果amount列里混了一个文本"N/A",导致整个求和结果为NULL。从那以后,我每次都会先检查数据类型。
AVG函数详解(平均值)
6.1 基础语法
sql
AVG(列名) -- 对数值列求平均值,自动忽略NULL
6.2 电商实操案例
案例一:计算全店平均客单价(已支付订单的平均金额)
sql
SELECT AVG(amount) AS avg_order_value FROM orders WHERE order_status = '已支付';
预期结果:2944 / 6 ≈ 490.67。
案例二:计算女装旗舰店已支付订单的平均件单价(金额/数量?这里简化:平均每笔订单金额)
sql
SELECT AVG(amount) FROM orders WHERE shop_name = '女装旗舰店' AND order_status = '已支付';
预期结果:(299+399+1299+89)/4 = 2086/4=521.5。
案例三:计算每个用户平均下单金额(需配合GROUP BY,但这里先演示整体)
sql
SELECT AVG(amount) FROM orders WHERE order_status = '已支付';
6.3 分步操作
-
筛选数据。
-
用
AVG计算。 -
执行验证。
避坑提醒:
-
AVG只对数值列有效。 -
AVG会忽略NULL,但不会忽略0。0会拉低平均值,要根据业务决定是否排除。
实操避坑提醒 :客单价 = GMV / 订单数,不等于
AVG(amount)吗?是的,因为AVG(amount)就是总金额除以订单数。但如果订单有多个商品,amount已经是订单总金额,那么AVG(amount)就是客单价。
MAX/MIN函数详解(最大/最小值)
7.1 基础语法
sql
MAX(列名) -- 最大值
MIN(列名) -- 最小值
7.2 电商实操案例
案例一:找出最高订单金额
sql
SELECT MAX(amount) AS max_amount FROM orders;
预期结果:1299。
案例二:找出最低订单金额(已支付订单)
sql
SELECT MIN(amount) AS min_amount FROM orders WHERE order_status = '已支付';
预期结果:89(ORD008)。
案例三:找出最早和最晚的下单时间
sql
SELECT MIN(create_time) AS first_order, MAX(create_time) AS last_order FROM orders;
预期结果:2025-06-01 10:00:00 和 2025-06-05 14:00:00。
案例四:在商品表中找出最高和最低价格(假设有商品表)
sql
-- 创建商品表
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
price DECIMAL(10,2)
);
INSERT INTO products VALUES (1, '连衣裙', 299), (2, 'T恤', 89), (3, '牛仔裤', 199);
SELECT MAX(price), MIN(price) FROM products;
7.3 分步操作
-
筛选条件(可选)。
-
用
MAX或MIN。 -
执行验证。
避坑提醒:
-
MAX/MIN对文本列按字典序比较。 -
对日期列也能正确比较。
我的踩坑经历 :我用
MAX(product_name)找最晚的商品名称,结果返回了字典序最大的,不是按时间。排序和聚合要分清。
多个聚合函数的组合用法
8.1 基础语法
可以在一个SELECT中同时使用多个聚合函数,得到一站式统计。
sql
SELECT
COUNT(*) AS total_orders,
SUM(amount) AS gmv,
AVG(amount) AS avg_price,
MAX(amount) AS max_price,
MIN(amount) AS min_price
FROM orders
WHERE order_status = '已支付';
8.2 电商实操案例
案例一:全店经营核心指标(已支付订单)
sql
SELECT
COUNT(*) AS order_cnt,
SUM(amount) AS gmv,
ROUND(AVG(amount), 2) AS avg_order_value,
MAX(amount) AS max_order,
MIN(amount) AS min_order
FROM orders
WHERE order_status = '已支付';
预期结果:order_cnt=6, gmv=2944, avg_order_value=490.67, max=1299, min=89。
案例二:女装旗舰店的销售汇总
sql
SELECT
COUNT(*) AS orders,
SUM(amount) AS gmv,
SUM(quantity) AS items_sold,
AVG(amount) AS avg_price,
MAX(amount) AS highest,
MIN(amount) AS lowest
FROM orders
WHERE shop_name = '女装旗舰店' AND order_status = '已支付';
预期结果:orders=4, gmv=2086, items_sold=14, avg_price=521.5, highest=1299, lowest=89。
案例三:按店铺分组统计(预告下一章内容,这里简单展示)
sql
SELECT
shop_name,
COUNT(*) AS order_cnt,
SUM(amount) AS gmv
FROM orders
WHERE order_status = '已支付'
GROUP BY shop_name;
8.3 分步操作
-
确定要统计的指标。
-
写出所有聚合函数,给别名。
-
添加
WHERE条件(可选)。 -
执行并验证。
避坑提醒:
-
聚合函数不能与普通列混用(除非有
GROUP BY)。例如SELECT order_id, COUNT(*) FROM orders会报错。 -
多个聚合函数互相独立,计算顺序不影响结果。
实操避坑提醒 :在计算平均值前,如果要去除异常值,可以在
WHERE中先过滤。例如WHERE amount BETWEEN 10 AND 10000。
综合实操案例:服饰类目店铺月度经营核心指标统计
9.1 案例背景
某服饰类目店铺需要生成一份6月份的经营汇总报表,包含以下指标:
-
总订单数(所有状态)。
-
有效订单数(已支付+已完成)。
-
GMV(已支付+已完成的金额总和)。
-
客单价(GMV / 有效订单数)。
-
最高订单金额、最低订单金额。
-
总销量(数量总和,有效订单)。
-
独立用户数(去重)。
9.2 分步操作
步骤1:总订单数
sql
SELECT COUNT(*) AS total_orders FROM orders WHERE create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤2:有效订单数
sql
SELECT COUNT(*) AS valid_orders FROM orders
WHERE order_status IN ('已支付', '已完成') AND create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤3:GMV
sql
SELECT SUM(amount) AS gmv FROM orders
WHERE order_status IN ('已支付', '已完成') AND create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤4:客单价
sql
SELECT ROUND(SUM(amount) / COUNT(*), 2) AS avg_order_value FROM orders
WHERE order_status IN ('已支付', '已完成') AND create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤5:最高/最低订单金额(有效订单)
sql
SELECT MAX(amount) AS max_amount, MIN(amount) AS min_amount FROM orders
WHERE order_status IN ('已支付', '已完成') AND create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤6:总销量(有效订单的数量总和)
sql
SELECT SUM(quantity) AS total_items FROM orders
WHERE order_status IN ('已支付', '已完成') AND create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤7:独立用户数(有效订单)
sql
SELECT COUNT(DISTINCT user_id) AS unique_users FROM orders
WHERE order_status IN ('已支付', '已完成') AND create_time BETWEEN '2025-06-01' AND '2025-06-30';
步骤8:一站式查询(组合)
sql
SELECT
COUNT(*) AS total_orders,
SUM(CASE WHEN order_status IN ('已支付','已完成') THEN 1 ELSE 0 END) AS valid_orders,
SUM(CASE WHEN order_status IN ('已支付','已完成') THEN amount ELSE 0 END) AS gmv,
ROUND(SUM(CASE WHEN order_status IN ('已支付','已完成') THEN amount ELSE 0 END) /
NULLIF(SUM(CASE WHEN order_status IN ('已支付','已完成') THEN 1 ELSE 0 END), 0), 2) AS avg_order_value,
MAX(CASE WHEN order_status IN ('已支付','已完成') THEN amount ELSE NULL END) AS max_amount,
MIN(CASE WHEN order_status IN ('已支付','已完成') THEN amount ELSE NULL END) AS min_amount,
SUM(CASE WHEN order_status IN ('已支付','已完成') THEN quantity ELSE 0 END) AS total_items,
COUNT(DISTINCT CASE WHEN order_status IN ('已支付','已完成') THEN user_id END) AS unique_users
FROM orders
WHERE create_time BETWEEN '2025-06-01' AND '2025-06-30';
9.3 结果验证
执行一站式查询,检查数据逻辑(如客单价 = GMV / 有效订单数)。
📌 电商数据合规提示 :在统计独立用户数时,使用内部匿名
user_id,不要涉及手机号等敏感信息。汇总指标(如GMV、客单价)属于经营数据,内部共享时注意权限控制。
本章踩坑清单与合规总结
10.1 新手常见踩坑
| 错误 | 原因 | 正确做法 |
|---|---|---|
COUNT(column)忽略NULL导致计数偏少 |
不理解NULL处理 | 用COUNT(*)或确保列非空 |
| 金额列包含非数字字符 | 求和结果为0或NULL | 先清洗数据,转换类型 |
AVG包含0值 |
0拉低平均值 | 根据业务决定是否排除0 |
聚合函数与普通列混用无GROUP BY |
语法错误 | 要么全聚合,要么加GROUP BY |
SUM(amount)未过滤无效订单 |
统计了退款订单 | 加WHERE order_status = '已支付' |
10.2 性能优化建议
-
为
WHERE条件中的列(如create_time、order_status)建立索引。 -
避免在聚合函数中使用
DISTINCT处理大数据量,可先用子查询去重。
10.3 电商数据合规红线
-
统计指标不要包含个人标识:如统计用户数时,只输出数字,不输出用户ID列表。
-
GMV等核心指标:内部报表需加密传输,避免泄露。
-
退款金额统计:注意区分"退款"和"取消",业务定义要清晰。
结语
聚合函数是SQL统计分析的基石。掌握COUNT、SUM、AVG、MAX、MIN,你就能独立计算电商核心经营指标。
有问题的评论区留言,我看到会回复。