select sum(java) from student;
+-----------+
| sum(java) |
+-----------+
| 453.00 |
+-----------+
-- 1 row in set (0.01 sec)
ログイン後にコピー
虽然我们表中有 java 字段这列中有 null 值,前面了解到 null 与任何值运算都是 null,但是这里的 sum 函数会避免这种情况发生。
当然在后面也可也带上 where 条件,这里就不做过多演示了。
3.1.3 avg
● 求班级中 java 的平均分
select avg(java) from student;
+-----------+
| avg(java) |
+-----------+
| 90.600000 |
+-----------+
-- 1 row in set (0.00 sec)
ログイン後にコピー
当前只是针对某一列进行平均运算,如果有两门课程,求每个学生总分的平均分呢?
select avg(java + python) from student;
ログイン後にコピー
这里每次查询结果都只有一列,能否把两个聚合函数一起使用呢?
select sum(java), avg(java) as '平均分' from student;
+-----------+-----------+
| sum(java) | 平均分 |
+-----------+-----------+
| 453.00 | 90.600000 |
+-----------+-----------+
-- 1 row in set (0.00 sec)
ログイン後にコピー
这里我们能发现一个细节,使用聚合函数查询,字段也是可以取别名的。
3.1.4 max 和 min
● 求出 java 考试分数的最高分和最低分
select max(java) as '最高分', min(java) as '最低分' from student;
+-----------+-----------+
| 最高分 | 最低分 |
+-----------+-----------+
| 96.00 | 83.40 |
+-----------+-----------+
-- 1 row in set (0.00 sec)
ログイン後にコピー
上述就是聚合函数最基础的用法了, 但是在实际中也可能会有更复杂的情况,比如需要按照某某进行分组查询,这就需要搭配 GROUP BY 字句了。
4、GROUP BY 子句
select 中使用 group by 自居可以对指定列进行分组查询,但是需要满足指定分组的字段必须是 "分组依据字段",其他字段若想出现在 select 中,则必须包含在聚合函数中。
这里我们构造出一张薪水表 salary:
create table salary (
id int primary key,
name varchar(20),
role varchar(20),
income int
);
insert into salary value
(1, '麻花疼', '老板', 5000000),
(2, '篮球哥', '程序猿', 3000),
(3, '歪嘴猴', '经理', 20000),
(4, '多嘴鸟', '经理', 25000),
(5, '雷小君', '老板', 3000000),
(6, '阿紫姐', '程序猿', 5000);
ログイン後にコピー
像上述的情况,如果要查平均工资,那公平吗???
select avg(income) from salary;
+--------------+
| avg(income) |
+--------------+
| 1342166.6667 |
+--------------+
-- 1 row in set (0.00 sec)
ログイン後にコピー
那篮球哥的月薪连平均下来的零头都不到,所以这样去求平均工资是毫无意义的,真正有意义的是啥呢?求老板这个职位的平均工资,以及经理这个职位的平均工资,及程序猿这个职位的平均工资,通俗来说,就是按照 role 这个字段进行分组。每一组求平均工资:
select role, avg(income) from salary group by role;
+-----------+--------------+
| role | avg(income) |
+-----------+--------------+
| 程序猿 | 4000.0000 |
| 经理 | 22500.0000 |
| 老板 | 4000000.0000 |
+-----------+--------------+
-- 3 rows in set (0.00 sec)
ログイン後にコピー
此句可以重写为:这是将role列中值相同的行分为一组,然后按组计算平均值,也是针对每个组分别计算。
在 MySQL 中,这里得到的查询结果临时表,如果没有 order by 指定列排序,这里的顺序是不可预期的,当然也可以手动指定排序,比如最终结果按照平均工资降序排序:
select role, avg(income) from salary group by role order by avg(income) desc;
+-----------+--------------+
| role | avg(income) |
+-----------+--------------+
| 老板 | 4000000.0000 |
| 经理 | 22500.0000 |
| 程序猿 | 4000.0000 |
+-----------+--------------+
-- 3 rows in set (0.00 sec)
ログイン後にコピー
如果不带聚合函数的普通查询,能否可行呢?这里如果你没有修改任何配置文件,是不可行的,记住千万不能把前面的 order by 与 group by 弄混!
select role, avg(income) from salary where name != '篮球哥' group by role;
+-----------+--------------+
| role | avg(income) |
+-----------+--------------+
| 程序猿 | 5000.0000 |
| 经理 | 22500.0000 |
| 老板 | 4000000.0000 |
+-----------+--------------+
-- 3 rows in set (0.00 sec)
ログイン後にコピー
这样求出来的平均值就不包含篮球哥的月薪数据了,这就是先筛选,再分组。
● 还是查询每个岗位的平均工资,但是除去平均月薪在 10w 以上的岗位,不能让篮球哥眼红!
select role, avg(income) from salary group by role having avg(income) < 100000;
+-----------+-------------+
| role | avg(income) |
+-----------+-------------+
| 程序猿 | 4000.0000 |
| 经理 | 22500.0000 |
+-----------+-------------+
-- 2 rows in set (0.00 sec)