MySQL聚合查询:COUNT、SUM、AVG用法,实战案例演示

前言

日常开发中,我们经常需要对数据进行「统计分析」,比如:统计用户总数、计算平均年龄、求和订单金额,这时候就需要用到 MySQL 聚合函数。

最常用的聚合函数有3个:COUNT(计数)、SUM(求和)、AVG(求平均),本篇用实战案例,讲透每个函数的用法、场景和避坑点,新手能直接套用。

继续使用前面的user表,新增一张订单表(增加实战场景):

sql 复制代码
-- 创建订单表 order(注意order是关键字,用反引号包裹)
CREATE TABLE `order` (
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,  -- 关联用户表主键
    amount DECIMAL(10,2),  -- 订单金额(保留2位小数)
    create_time DATETIME DEFAULT NOW()
);
sql 复制代码
-- 插入订单测试数据
INSERT INTO `order` (user_id, amount) 
VALUES 
(1, 99.90),
(1, 199.90),
(2, 59.90),
(3, 299.90),
(4, 159.90),
(4, 89.90);

一、COUNT:计数(最常用)

核心作用:统计符合条件的「记录条数」,有3种常用写法,重点区分差异。

1. COUNT(*)

统计所有记录条数,包括 NULL 值(最常用、效率最高)。

sql 复制代码
-- 1. 统计用户总数
SELECT COUNT(*) AS user_total FROM user;

-- 2. 统计性别为男的用户数
SELECT COUNT(*) AS male_total FROM user WHERE gender = 1;

-- 3. 统计订单总数
SELECT COUNT(*) AS order_total FROM `order`;

2. COUNT(字段名)

统计该字段「非NULL值」的记录条数,忽略NULL值。

sql 复制代码
-- 统计age字段非NULL的用户数(如果有用户age为NULL,会被排除)
SELECT COUNT(age) AS age_not_null FROM user;

3. COUNT(DISTINCT 字段名)

统计该字段「非NULL且不重复」的记录条数。

sql 复制代码
-- 统计有订单的不同用户数(一个用户可能有多个订单,只算1次)
SELECT COUNT(DISTINCT user_id) AS user_with_order FROM `order`;

COUNT避坑

❌ 错误:用COUNT(字段名)统计总条数,忽略了NULL值,导致统计结果偏小;

✅ 正确:统计总条数优先用 COUNT(*),统计非NULL字段用 COUNT(字段名)。


二、SUM:求和

核心作用:对指定「数值类型字段」求和,忽略NULL值,非数值类型求和会返回0。

sql 复制代码
-- 1. 统计所有订单的总金额
SELECT SUM(amount) AS total_amount FROM `order`;

-- 2. 统计用户id=1的所有订单金额总和
SELECT SUM(amount) AS user1_total FROM `order` WHERE user_id = 1;

-- 3. 非数值字段求和(返回0,无意义)
SELECT SUM(name) AS wrong_sum FROM user;

SUM避坑

❌ 错误:对非数值字段(如name、email)使用SUM,结果无意义;

✅ 正确:SUM仅用于数值类型字段(int、decimal等)。


三、AVG:求平均

核心作用:对指定「数值类型字段」求平均值,忽略NULL值,计算逻辑:总和 ÷ 非NULL记录数。

sql 复制代码
-- 1. 计算所有用户的平均年龄
SELECT AVG(age) AS avg_age FROM user;

-- 2. 计算所有订单的平均金额(保留2位小数,用ROUND函数)
SELECT ROUND(AVG(amount), 2) AS avg_amount FROM `order`;

-- 3. 计算性别为女的用户平均年龄
SELECT AVG(age) AS female_avg_age FROM user WHERE gender = 2;

AVG避坑

❌ 错误:忽略NULL值的影响,比如部分用户age为NULL,会导致平均年龄计算偏差;

✅ 正确:如果需要包含NULL值(按0计算),可搭配IFNULL函数:SELECT AVG(IFNULL(age, 0)) FROM user;


四、聚合查询实战案例

需求:统计有订单的用户中,年龄大于20的用户数、他们的平均年龄、以及他们的订单总金额。

sql 复制代码
SELECT 
    COUNT(DISTINCT u.id) AS target_user,  -- 符合条件的用户数
    ROUND(AVG(u.age), 2) AS avg_age,      -- 平均年龄
    SUM(o.amount) AS total_order_amount   -- 订单总金额
FROM user u
LEFT JOIN `order` o ON u.id = o.user_id  -- 关联用户表和订单表
WHERE u.age > 20 AND o.user_id IS NOT NULL;  -- 有订单且年龄>20

五、总结

  1. COUNT:计数,优先用COUNT(*),统计非NULL用COUNT(字段),去重计数用COUNT(DISTINCT 字段);

  2. SUM:对数值字段求和,忽略NULL,非数值字段返回0;

  3. AVG:对数值字段求平均,忽略NULL,可搭配ROUND函数保留小数。

相关推荐
刘大猫.1 小时前
重塑经典:Snapseed4.0全面登陆安卓,内置“胶片相机”与专业手动模式
android·数码相机·ai·机器人·大模型·算力·snapseed4.0
woxihuan1234561 小时前
如何为禁用按钮添加点击提示信息
jvm·数据库·python
ㄟ留恋さ寂寞1 小时前
Golang怎么限制请求Body大小_Golang如何防止客户端发送过大的请求体【避坑】
jvm·数据库·python
老纪2 小时前
CSS Flex布局中如何实现导航栏与Logo的左右分布_利用justify-content- space-between
jvm·数据库·python
沅霖2 小时前
Android Studio Java工程开发环境,怎么切换到Kotlin开发环境
android·kotlin·android studio
会编程的土豆2 小时前
Go ini 配置加载:`ini.MapTo` 详细解析
开发语言·数据库·golang
largecode2 小时前
企业名称能在来电显示吗?号码显示公司名服务打通多终端展示
android·xml·ios·iphone·xcode·webview·phonegap
龙之叶2 小时前
Android 12:从 Editor 到 FloatingToolbar 全局收敛长按菜单
android
今天也是元气满满的一天呢2 小时前
详解SQL注入问题
网络·数据库·sql