mysql> select id,name,math+chinese+english as 总分 from exam_result;+----+-----------+--------+| id | name | 总分 |+----+-----------+--------+| 1 | 唐三藏 | 221 || 2 | 孙悟空 | 242 || 3 | 猪悟能 | 276 || 4 | 曹孟德 | 233 || 5 | 刘玄德 | 185 || 6 | 孙权 | 221 || 7 | 宋公明 | 170 |+----+-----------+--------+7 rows in set (0.00 sec)
⑤ 结果去重 distinct
-- 去重前mysql> select math+chinese+english as 总分 from exam_result;+--------+| 总分 |+--------+| 221 || 242 || 276 || 233 || 185 || 221 || 170 |+--------+7 rows in set (0.00 sec)-- 去重后mysql> select distinct math+chinese+english as 总分 from exam_result;+--------+| 总分 |+--------+| 221 || 242 || 276 || 233 || 185 || 170 |+--------+6 rows in set (0.00 sec)
2、where 条件
这里的 where 条件其实就是对我们已经选择的列字段,进行某种条件筛选的策略!其实就相当于我们以前在学 c/c++ 的时候所学的 if 语句,所以肯定也有对应的比较、逻辑运算符供我们使用!
要注意的是,别名不能用在 where 条件中!
🎏 where 条件在 sql 语句中的执行顺序
为什么强调这个执行顺序呢❓❓❓
这是因为只有当我们理解了执行顺序之后,才会理解一些 mysql 的错误语句到底错在哪,或者是要做什么工作!
比如为什么不能在 where 语句中使用别名,这是因为别名是在 select 部分使用的,是为了最后呈现出来表字段的别名。如果在 where 语句使用了 select 语句部分的别名,那么因为执行顺序问题,where 语句在 select 语句之前就执行了,肯定就找不到该别名去执行,就报错了!
比较运算符
运算符
说明
>、≥、<、≤
大于,大于等于,小于,小于等于
=
等于,对于 NULL 不安全,例如 NULL = NULL 的结果是 NULL
<=>
等于,对于 NULL 安全,例如 NULL <=> NULL 的结果是 TRUE/1
!=、<>
不等于
between a and b
范围匹配为 [a, b],如果 a ≤ value ≤ b,返回 TRUE/1
in (option, ...)
如果是 option 中的任意一个,返回 TRUE/1
is null
判断是否为 null
is not null
判断是否不为 null
like
模糊匹配,% 表示任意多个(包括 0 个)任意字,_ 表示任意一个字符
逻辑运算符
运算符
说明
and
多个条件必须都为 TRUE/1,结果才是 TRUE/1
or
任意一个条件为 TRUE/1,结果为 TRUE/1
not
条件为 TRUE/1,结果为 FALSE/0
使用案例
① 英语不及格的同学及英语成绩,即小于60分
-- 筛选前mysql> select name,english as '英语' from exam_result;+-----------+--------+| name | 英语 |+-----------+--------+| 唐三藏 | 56 || 孙悟空 | 77 || 猪悟能 | 90 || 曹孟德 | 67 || 刘玄德 | 45 || 孙权 | 78 || 宋公明 | 30 |+-----------+--------+7 rows in set (0.00 sec)-- 筛选后mysql> select name,english as '英语' from exam_result where english < 60;+-----------+--------+| name | 英语 |+-----------+--------+| 唐三藏 | 56 || 刘玄德 | 45 || 宋公明 | 30 |+-----------+--------+3 rows in set (0.00 sec)
② 语文成绩在 [80, 90] 分的同学及语文成绩
除了下面的 between and 之外,还可以使用 and,但是太麻烦了,这里就不演示了!
-- 筛选前mysql> select name,chinese as '语文' from exam_result;+-----------+--------+| name | 语文 |+-----------+--------+| 唐三藏 | 67 || 孙悟空 | 87 || 猪悟能 | 88 || 曹孟德 | 82 || 刘玄德 | 55 || 孙权 | 70 || 宋公明 | 75 |+-----------+--------+7 rows in set (0.00 sec)-- 使用between and筛选mysql> select name,chinese as '语文' from exam_result where chinese between 80 and 90;+-----------+--------+| name | 语文 |+-----------+--------+| 孙悟空 | 87 || 猪悟能 | 88 || 曹孟德 | 82 |+-----------+--------+3 rows in set (0.00 sec)
③ 数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
-- 筛选前mysql> select name,math as '数学' from exam_result;+-----------+--------+| name | 数学 |+-----------+--------+| 唐三藏 | 98 || 孙悟空 | 78 || 猪悟能 | 98 || 曹孟德 | 84 || 刘玄德 | 85 || 孙权 | 73 || 宋公明 | 65 |+-----------+--------+7 rows in set (0.00 sec)-- 使用or筛选mysql> select name,math as '数学' from exam_result where math=58 or math=59 or math=98 or math=99;+-----------+--------+| name | 数学 |+-----------+--------+| 唐三藏 | 98 || 猪悟能 | 98 |+-----------+--------+2 rows in set (0.00 sec)
还可用 in 进行筛选,更加的优雅:
-- 使用in筛选,更加的优雅!mysql> select name,math as '数学' from exam_result where math in(58, 59, 98, 99);+-----------+--------+| name | 数学 |+-----------+--------+| 唐三藏 | 98 || 猪悟能 | 98 |+-----------+--------+2 rows in set (0.00 sec)
-- 筛选前mysql> select name from exam_result;+-----------+| name |+-----------+| 唐三藏 || 孙悟空 || 猪悟能 || 曹孟德 || 刘玄德 || 孙权 || 宋公明 |+-----------+7 rows in set (0.00 sec)-- 通过like以及两个通配符来筛选,两者用or连接-- % 表示匹配任意多个(包括0个)任意字符-- _ 表示匹配严格的一个任意字符mysql> select name from exam_result where name like '孙%' or name like '孙_';+-----------+| name |+-----------+| 孙悟空 || 孙权 |+-----------+2 rows in set (0.00 sec)
⑤ 语文成绩好于英语成绩的同学
-- 筛选前mysql> select name,chinese as '语文',math as '数学' from exam_result;+-----------+--------+--------+| name | 语文 | 数学 |+-----------+--------+--------+| 唐三藏 | 67 | 98 || 孙悟空 | 87 | 78 || 猪悟能 | 88 | 98 || 曹孟德 | 82 | 84 || 刘玄德 | 55 | 85 || 孙权 | 70 | 73 || 宋公明 | 75 | 65 |+-----------+--------+--------+7 rows in set (0.00 sec)-- 筛选后mysql> select name,chinese as '语文',math as '数学' from exam_result where chinese > math;+-----------+--------+--------+| name | 语文 | 数学 |+-----------+--------+--------+| 孙悟空 | 87 | 78 || 宋公明 | 75 | 65 |+-----------+--------+--------+2 rows in set (0.00 sec)
⑥ 总分在 200 分以上的同学
这里需要注意的是,别名不能用在 where 条件中!具体原因是和语句的执行有关,上面讲过!
-- 筛选前mysql> select name, chinese+math+english '总分' from exam_result;+-----------+--------+| name | 总分 |+-----------+--------+| 唐三藏 | 221 || 孙悟空 | 242 || 猪悟能 | 276 || 曹孟德 | 233 || 刘玄德 | 185 || 孙权 | 221 || 宋公明 | 170 |+-----------+--------+7 rows in set (0.00 sec)-- 筛选后mysql> select name, chinese+math+english '总分' from exam_result where chinese+math+english > 200;+-----------+--------+| name | 总分 |+-----------+--------+| 唐三藏 | 221 || 孙悟空 | 242 || 猪悟能 | 276 || 曹孟德 | 233 || 孙权 | 221 |+-----------+--------+5 rows in set (0.00 sec)
⑦ 语文成绩 > 80 并且不姓孙的同学
-- 筛选前mysql> select name, chinese from exam_result where chinese>80;+-----------+---------+| name | chinese |+-----------+---------+| 孙悟空 | 87 || 猪悟能 | 88 || 曹孟德 | 82 |+-----------+---------+3 rows in set (0.00 sec)-- 通过and和not配合达到筛选目的mysql> select name, chinese from exam_result where chinese>80 and name not like '孙%';+-----------+---------+| name | chinese |+-----------+---------+| 猪悟能 | 88 || 曹孟德 | 82 |+-----------+---------+2 rows in set (0.00 sec)
⑧ 某猪同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
mysql> select name,chinese,math,english,chinese+math+english '总分' from exam_result where name like '猪%' and chinese+math+english>200 and chineese<math and english>80;+-----------+---------+------+---------+--------+| name | chinese | math | english | 总分 |+-----------+---------+------+---------+--------+| 猪悟能 | 88 | 98 | 90 | 276 |+-----------+---------+------+---------+--------+1 row in set (0.00 sec)
⑨ NULL 的查询
-- 查询 students 表+-----+-------+-----------+-------+| id | sn | name | qq |+-----+-------+-----------+-------+| 100 | 10010 | 唐大师 | NULL || 101 | 10001 | 孙悟空 | 11111 || 103 | 20002 | 孙仲谋 | NULL || 104 | 20001 | 曹阿瞒 | NULL |+-----+-------+-----------+-------+4 rows in set (0.00 sec)-- 查询 qq 号已知的同学姓名select name, qq from students where qq is not NULL;+-----------+-------+| name | qq |+-----------+-------+| 孙悟空 | 11111 |+-----------+-------+1 row in set (0.00 sec)
如果要按多个列进行排序,可以在 order by 子句中指定多个列名,并用逗号分隔它们。查询结果将首先按第一个列进行排序,然后按第二个列进行排序,以此类推。
注意事项:
没有 order by 子句的查询,返回的顺序是未定义的,永远不要依赖原来的插入表的这个顺序!
多字段排序,排序优先级随书写顺序!(可以结合下面的案例③)
order by 子句中是可以使用列别名的!(这个和子句的执行顺序有关系!)
order by 子句必须放在 where 条件后面使用!
🎏order by子句在 sql 语句中的执行顺序
从上图可以清晰看到执行的顺序,最重要的是第三步也就是 select 子句,它虽然是进行筛选和显示的执行,但是其实它这两个步骤是分开的,当加入了 order by 子句之后,select 子句会先进行筛选,目的是筛选出符合条件的数据集,然后再交给第四步也就是 order by 子句进行排序,最后再回到 select 子句中进行最后的显示!
这也是为什么 order by 子句可以使用 select 子句中的别名的原因!
使用案例
① 同学及数学成绩,按数学成绩升序显示
mysql> select name,math from exam_result order by math asc; #升序+-----------+------+| name | math |+-----------+------+| 宋公明 | 65 || 孙权 | 73 || 孙悟空 | 78 || 曹孟德 | 84 || 刘玄德 | 85 || 唐三藏 | 98 || 猪悟能 | 98 |+-----------+------+7 rows in set (0.00 sec)mysql> select name,math from exam_result order by math desc; #降序+-----------+------+| name | math |+-----------+------+| 唐三藏 | 98 || 猪悟能 | 98 || 刘玄德 | 85 || 曹孟德 | 84 || 孙悟空 | 78 || 孙权 | 73 || 宋公明 | 65 |+-----------+------+7 rows in set (0.00 sec)
② 同学及 qq 号,按 qq 号排序显示
-- NULL 视为比任何值都小,升序出现在最上面select name, qq from students order by qq;+-----------+-------+| name | qq |+-----------+-------+| 唐大师 | NULL || 孙仲谋 | NULL || 曹阿瞒 | NULL || 孙悟空 | 11111|+-----------+-------+4 rows in set (0.00 sec)-- NULL 视为比任何值都小,降序出现在最下面select name, qq from students order by qq desc;+-----------+-------+| name | qq |+-----------+-------+| 孙悟空 | 11111 || 唐大师 | NULL || 孙仲谋 | NULL || 曹阿瞒 | NULL |+-----------+-------+4 rows in set (0.00 sec)
③ 查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示
注意,多字段排序,排序优先级随书写顺序!所以如果 math 高的话,就算 english 低了也会排在前面!
mysql> select name,math,english,chinese from exam_result order by math desc,english asc,chinese asc;+-----------+------+---------+---------+| name | math | english | chinese |+-----------+------+---------+---------+| 唐三藏 | 98 | 56 | 67 || 猪悟能 | 98 | 90 | 88 || 刘玄德 | 85 | 45 | 55 || 曹孟德 | 84 | 67 | 82 || 孙悟空 | 78 | 77 | 87 || 孙权 | 73 | 78 | 70 || 宋公明 | 65 | 30 | 75 |+-----------+------+---------+---------+7 rows in set (0.00 sec)
④ 查询同学及总分,由高到低
说明 order by 中也可以使用表达式!
mysql> select name,chinese+math+english as '总分' from exam_result order by chinese+math+english desc;+-----------+--------+| name | 总分 |+-----------+--------+| 猪悟能 | 276 || 孙悟空 | 242 || 曹孟德 | 233 || 唐三藏 | 221 || 孙权 | 221 || 刘玄德 | 185 || 宋公明 | 170 |+-----------+--------+7 rows in set (0.00 sec)
除此之外,order by 子句中是可以使用列别名的:
mysql> select name,chinese+math+english as '总分' from exam_result order by '总分' desc;+-----------+--------+| name | 总分 |+-----------+--------+| 唐三藏 | 221 || 孙悟空 | 242 || 猪悟能 | 276 || 曹孟德 | 233 || 刘玄德 | 185 || 孙权 | 221 || 宋公明 | 170 |+-----------+--------+7 rows in set (0.00 sec)
⑤ 查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
从下面的操作可以看出 order by 子句要放在 where 条件的后面!
mysql> select name,math from exam_result where name like '孙%' or name like '曹%' order by math desc;+-----------+------+| name | math |+-----------+------+| 曹孟德 | 84 || 孙悟空 | 78 || 孙权 | 73 |+-----------+------+3 rows in set (0.00 sec)-- order by子句要放在where条件的后面!mysql> select name,math from exam_result order by math desc where name like '孙%' or name like '曹%';ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where name like '孙%' or name like '曹%'' at line 1
# 从 0 开始,筛选 n 条结果select 列名 from 表名 [where ...] [order by ...] limit n;# 从 s 开始,筛选 n 条结果select 列名 from 表名 [where ...] [order by ...] limit s, n;# 从 s 开始,筛选 n 条结果,比第二种用法更明确,更建议使用!select 列名 from 表名 [where ...] [order by ...] limit n offset s;
update 表名 set column1=value1 [, column2=value2, ...] [where 条件] [order by ...] [limit ...];
注意,如果没有指定 where 子句,update 语句将会更新表中的所有行。因此,在使用 update 语句时,请确保提供正确的条件,以避免意外更新整个表的数据。
2、使用案例
① 将孙悟空同学的数学成绩变更为 80 分
-- 查看原数据mysql> select name,math from exam_result where name='孙悟空';+-----------+------+| name | math |+-----------+------+| 孙悟空 | 78 |+-----------+------+1 row in set (0.00 sec)-- 数据更新mysql> update exam_result set math=80 where name='孙悟空';Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0-- 查看更新后数据mysql> select name,math from exam_result where name='孙悟空';+-----------+------+| name | math |+-----------+------+| 孙悟空 | 80 |+-----------+------+1 row in set (0.00 sec)
② 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分
-- 一次更新多个列-- 查看原数据mysql> select name,math,chinese from exam_result where name='曹孟德';+-----------+------+---------+| name | math | chinese |+-----------+------+---------+| 曹孟德 | 84 | 82 |+-----------+------+---------+1 row in set (0.00 sec)-- 数据更新mysql> update exam_result set math=60,chinese=70 where name='曹孟德';Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0-- 查看更新后数据mysql> select name,math,chinese from exam_result where name='曹孟德';+-----------+------+---------+| name | math | chinese |+-----------+------+---------+| 曹孟德 | 60 | 70 |+-----------+------+---------+1 row in set (0.00 sec)
③ 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分
-- 更新值为原值基础上变更-- 查看原数据mysql> select name,math+chinese+english total from exam_result order by total asc limit 3;+-----------+-------+| name | total |+-----------+-------+| 宋公明 | 170 || 刘玄德 | 185 || 曹孟德 | 197 |+-----------+-------+3 rows in set (0.00 sec)-- 数据更新,注意mysql不支持math += 30这种语法mysql> update exam_result set math=math+30 order by math+chinese+english limit 3;Query OK, 3 rows affected (0.00 sec)Rows matched: 3 Changed: 3 Warnings: 0-- 按总成绩排序后查询结果mysql> select name,math+chinese+english total from exam_result order by total asc limit 3;+-----------+-------+| name | total |+-----------+-------+| 宋公明 | 200 || 刘玄德 | 215 || 唐三藏 | 221 |+-----------+-------+3 rows in set (0.00 sec)
④ 将所有同学的语文成绩更新为原来的 2 倍
注意:更新全表的语句慎用!
-- 没有 WHERE 子句,则更新全表-- 查看原数据mysql> select name,chinese from exam_result;+-----------+---------+| name | chinese |+-----------+---------+| 唐三藏 | 67 || 孙悟空 | 87 || 猪悟能 | 88 || 曹孟德 | 70 || 刘玄德 | 55 || 孙权 | 70 || 宋公明 | 75 |+-----------+---------+7 rows in set (0.00 sec)-- 数据更新mysql> update exam_result set chinese=chinese*2;Query OK, 7 rows affected (0.00 sec)Rows matched: 7 Changed: 7 Warnings: 0-- 查看更新后数据mysql> select name,chinese from exam_result;+-----------+---------+| name | chinese |+-----------+---------+| 唐三藏 | 134 || 孙悟空 | 174 || 猪悟能 | 176 || 曹孟德 | 140 || 刘玄德 | 110 || 孙权 | 140 || 宋公明 | 150 |+-----------+---------+7 rows in set (0.00 sec)
delete from 表名 [where 条件] [order by ...] [limit ...];
另外注意的是,这里说的删除操作,都是针对表中的数据,而不是删除表的操作的!
① 删除孙悟空同学的考试成绩
-- 查看原数据mysql> select * from exam_result where name='孙悟空';+----+-----------+---------+------+---------+| id | name | chinese | math | english |+----+-----------+---------+------+---------+| 2 | 孙悟空 | 174 | 80 | 77 |+----+-----------+---------+------+---------+1 row in set (0.00 sec)-- 删除数据mysql> delete from exam_result where name='孙悟空';Query OK, 1 row affected (0.00 sec)-- 查看删除结果mysql> select * from exam_result where name='孙悟空';Empty set (0.00 sec)
② 删除整张表数据
注意,删除整表操作要慎用!
-- 准备测试表create table for_delete ( id int primary key auto_increment, name varchar(20) );-- 插入测试数据insert into for_delete (name) values ('A'), ('B'), ('C');-- 查看测试数据mysql> select * from for_delete;+----+------+| id | name |+----+------+| 1 | A || 2 | B || 3 | C |+----+------+3 rows in set (0.00 sec)
-- 删除整表数据mysql> delete from for_delete;Query OK, 3 rows affected (0.00 sec)-- 查看删除结果mysql> select * from for_delete;Empty set (0.00 sec)
-- 再插入一条数据,自增 id 在原值上增长mysql> insert into for_delete (name) values('liren');Query OK, 1 row affected (0.01 sec)-- 查看数据mysql> select * from for_delete;+----+-------+| id | name |+----+-------+| 4 | liren |+----+-------+1 row in set (0.00 sec)-- 查看表结构,会有 AUTO_INCREMENT=n 项,依然是不变的!这和下面的截断表不太一样!mysql> show create table for_delete\G;*************************** 1. row *************************** Table: for_deleteCreate Table: CREATE TABLE `for_delete` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf81 row in set (0.00 sec)
-- 准备测试表create table for_truncate ( id int primary key auto_increment, name varchar(20) );Query OK, 0 rows affected (0.02 sec)-- 插入测试数据insert into for_delete (name) values ('A'), ('B'), ('C');-- 查看测试数据mysql> select * from for_truncate;+----+------+| id | name |+----+------+| 1 | A || 2 | B || 3 | C |+----+------+3 rows in set (0.00 sec)
-- 截断整表数据,注意影响行数是 0,所以实际上没有对数据真正操作mysql> truncate table for_truncate;Query OK, 0 rows affected (0.01 sec)-- 查看删除结果mysql> select * from for_truncate;Empty set (0.00 sec)
-- 再插入一条数据,自增 id 在重新增长mysql> insert into for_truncate (name) values('liren');Query OK, 1 row affected (0.01 sec)-- 查看数据mysql> select * from for_truncate;+----+-------+| id | name |+----+-------+| 1 | liren |+----+-------+1 row in set (0.00 sec)-- 查看表结构,会有 AUTO_INCREMENT=2 项,这是因为我们重新插入了一条数据后的,说明auto_increment被重新设置了mysql> show create table for_truncate \G;*************************** 1. row *************************** Table: for_truncateCreate Table: CREATE TABLE `for_truncate` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf81 row in set (0.01 sec)
3、两者的区别
下面是 delete 和 truncate 之间的一些主要区别:
delete 语句是逐行删除数据,而 truncate 语句是一次性删除表中所有数据。
delete 语句可以使用 where 子句来指定删除的条件,而 truncate 语句不支持 where 子句。
-- 创建一张空表 no_duplicate_table,结构和 duplicate_table 一样mysql> create table no_duplicate_table like duplicate_table;Query OK, 0 rows affected (0.00 sec)-- 将 duplicate_table 的去重数据插入到 no_duplicate_tablemysql> insert into no_duplicate_table select distinct * from duplicate_table;Query OK, 3 rows affected (0.00 sec)Records: 3 Duplicates: 0 Warnings: 0-- 通过重命名表,实现原子的去重操作mysql> rename table duplicate_table to old_duplicate_table, no_duplicate_table to duplicate_table;Query OK, 0 rows affected (0.02 sec)-- 查看最终结果mysql> select * from duplicate_table;+------+------+| id | name |+------+------+| 100 | aaa || 200 | bbb || 300 | ccc |+------+------+3 rows in set (0.00 sec)mysql> select * from old_duplicate_table;+------+------+| id | name |+------+------+| 100 | aaa || 100 | aaa || 200 | bbb || 200 | bbb || 200 | bbb || 300 | ccc |+------+------+6 rows in set (0.00 sec)
Ⅵ. 聚合函数
1、常见聚合函数
这些常见的聚合函数可以与 select 语句一起使用,用于对数据进行汇总和统计操作:
函数
声明
count( [distinct] 列名 )
用于计算指定列或表中的行数
sum( [distinct] 列名 )
用于计算指定列或表中数值列的总和(不是数字没有意义)
avg( [distinct] 列名 )
用于计算指定列或表中数值列的平均值(不是数字没有意义)
max( [distinct] 列名 )
用于找出指定列或表中数值列的最大值(不是数字没有意义)
min( [distinct] 列名 )
用于找出指定列或表中数值列的最小值(不是数字没有意义)
group_concat( 列名 分隔符 )
用于将指定列的值连接成一个字符串,并用指定的分隔符分隔
注意,在使用聚合函数的时候,如果后面没有跟着 group by 指定的列字段的话,那么 select 语句是除了聚会函数以外,不能列举其它无关的列字段!
2、案例
① 统计班级共有多少同学
-- 最好使用 * 做统计,不受 NULL 影响mysql> select count(*) from exam_result;+----------+| count(*) |+----------+| 7 |+----------+1 row in set (0.00 sec)
② 统计班级收集的数学成绩有多少
-- NULL 不会计入结果mysql> select count(math) from exam_result;+-------------+| count(math) |+-------------+| 7 |+-------------+1 row in set (0.00 sec)
③ 统计本次考试的数学成绩分数去重后的个数
-- COUNT(DISTINCT math) 统计的是去重成绩数量mysql> select count(distinct math) from exam_result;+----------------------+| count(distinct math) |+----------------------+| 6 |+----------------------+1 row in set (0.01 sec)-- 可以使用别名mysql> select count(distinct math) 数学 from exam_result;+--------+| 数学 |+--------+| 6 |+--------+1 row in set (0.00 sec)
④ 统计数学成绩总分
mysql> select sum(math) 数学总分 from exam_result;+--------------+| 数学总分 |+--------------+| 581 |+--------------+1 row in set (0.00 sec)
⑤ 统计平均总分
mysql> select avg(chinese+math+english) 平均总分 from exam_result;+--------------------+| 平均总分 |+--------------------+| 221.14285714285714 |+--------------------+1 row in set (0.00 sec)
⑥ 返回英语最高分
mysql> select max(english) 英语 from exam_result;+--------+| 英语 |+--------+| 90 |+--------+1 row in set (0.00 sec)-- 注意不能select无关的列字段mysql> select name, max(english) 英语 from exam_result;ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'testdb.exam_result.name'; this is incompatible with sql_mode=only_full_group_by
⑦ 返回 > 70 分以上的数学最低分
mysql> select min(math) 数学 from exam_result where math>70;+--------+| 数学 |+--------+| 73 |+--------+1 row in set (0.00 sec)
Ⅶ. group by分组查询 && having 结果过滤
1、group by语法
在 mysql 中,group by 子句用于将结果集按照指定列进行分组。它通常与聚合函数(如 SUM、COUNT、AVG 等)一起使用,以便对每个组应用聚合函数并返回结果。
其语法如下:
select 列名1, 列名2, ... 列名n from 表名 [where 条件] group by 列名1, 列名2, ... 列名n;
在这个语法中,列名1,列名2,... 列名n 是想要按照其进行分组的列。我们可以指定一个或多个列作为分组依据,而 where 子句用于筛选出符合条件的行。
注意事项:
group by 子句的执行顺序是在 where 子句之后,在 select 子句之前的。
只要使用了 group by 子句,那么除了在 group by 中指定的列字段,以及聚合函数之外,其它列字段一般不能出现在 select 子句中。
having 经常和 group by 搭配使用,作用是对分组进行筛选,作用有些像 where,但是原理和 where 其实是不一样的!
mysql> select deptno 部门,avg(sal) 平均工资 from emp group by deptno having 平均工资<2000;+--------+--------------+| 部门 | 平均工资 |+--------+--------------+| 30 | 1566.666667 |+--------+--------------+1 row in set (0.00 sec)
下面顺便来看一下它和 where 子句的区别:
mysql> select deptno 部门,avg(sal) 平均工资 from emp where sal<2000 group by deptno;+--------+--------------+| 部门 | 平均工资 |+--------+--------------+| 10 | 1300.000000 || 20 | 950.000000 || 30 | 1310.000000 |+--------+--------------+3 rows in set (0.00 sec)
这是什么情况,为什么用 where 子句出来的有三个结果,而且其中部门一样的平均工资也不同呀❓❓
还记得我们上面注意事项中提到的 having 子句和 where 子句它们的执行顺序是不同的吗,where 语句是在 from 之后也就是选表之后执行的筛选,此时筛选出来的是整个 sal 字段中少于 2000 的那些工资,最后再拿这些少于 2000 的去分组聚合统计,最后得到该结果。
而 having 则是在分组聚合之后才拿到的数据,也就是之前整个 sal 字段的工资根据分组后聚合统计后,得到的结果,然后根据该结果再去筛选出来的最终结果,这无疑是不一样的操作,导致了不一样的结果,要区分开!