2.20 sql基础聚合函数(COUNT、SUM、AVG、MAX、MIN)

2.20 基础聚合函数(COUNT、SUM、AVG、MAX、MIN)

在电商数据分析中,你几乎每天都要用到聚合函数:

  • 统计总订单数(COUNT)。

  • 计算总销售额(SUM)。

  • 求平均客单价(AVG)。

  • 找最高/最低金额(MAX/MIN)。

这一章我会带你彻底搞懂五个最常用的聚合函数:COUNTSUMAVGMAXMIN。学完之后,你能独立完成电商核心经营指标的一站式统计。

学习前准备:

  • 已完成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 分步操作

  1. 确定要统计的对象(所有行、某列非空、去重)。

  2. 加上WHERE条件(如果需要)。

  3. 执行并验证。

避坑提醒

  • 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 分步操作

  1. 筛选有效订单(WHERE)。

  2. 对需要求和的列使用SUM

  3. 执行验证。

避坑提醒

  • 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 分步操作

  1. 筛选数据。

  2. AVG计算。

  3. 执行验证。

避坑提醒

  • 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 分步操作

  1. 筛选条件(可选)。

  2. MAXMIN

  3. 执行验证。

避坑提醒

  • 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 分步操作

  1. 确定要统计的指标。

  2. 写出所有聚合函数,给别名。

  3. 添加WHERE条件(可选)。

  4. 执行并验证。

避坑提醒

  • 聚合函数不能与普通列混用(除非有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_timeorder_status)建立索引。

  • 避免在聚合函数中使用DISTINCT处理大数据量,可先用子查询去重。

10.3 电商数据合规红线

  • 统计指标不要包含个人标识:如统计用户数时,只输出数字,不输出用户ID列表。

  • GMV等核心指标:内部报表需加密传输,避免泄露。

  • 退款金额统计:注意区分"退款"和"取消",业务定义要清晰。

结语

聚合函数是SQL统计分析的基石。掌握COUNTSUMAVGMAXMIN,你就能独立计算电商核心经营指标。

有问题的评论区留言,我看到会回复。

相关推荐
苏渡苇1 小时前
Redis 版本演进、新特性与协议那些事儿
数据库·redis·缓存·开源协议·redis版本·redis新特性
鬼蛟2 小时前
Nacos
数据库·redis·缓存
倔强的石头_2 小时前
NFS网络文件系统下企业级数据库安装排障实战:环境变量失效与权限问题的深度解析
数据库
Linux运维技术栈2 小时前
Cloudflare Argo Smart Routing全球加速:优化跨境回源链路,提升跨区域访问体验
大数据·前端·数据库
2402_854808372 小时前
CSS如何实现元素在容器内居中_利用margin-auto技巧
jvm·数据库·python
weixin_580614002 小时前
html标签怎么表示用户输入_kbd标签键盘快捷键标注【介绍】
jvm·数据库·python
m0_716430072 小时前
如何监控集群 interconnect_ping与traceroute验证心跳通畅.txt
jvm·数据库·python
m0_678485452 小时前
如何通过 curl 调用 Go 标准库 RPC 服务(JSON-RPC 协议)
jvm·数据库·python
Jul1en_2 小时前
【Redis】哈希类型命令、编码方式及应用场景
数据库·redis·哈希算法