目录
重点:
条件查询、分组分页、连接查询
难点:
条件查询、子查询
1.条件查询(上)
条件查询
刚才讲修改与删除的时候提到过where,使用where限定语句,查询集只返回条件为True的内容。
select * from students where id>13;
这个查询语句将会返回id大于10的数据,不会返回小于13的
案例:查询id不等于8
mysql> select * from students;
+----+----------+--------+
| ID | name | gender |
+----+----------+--------+
| 3 | 诸葛亮 | 1 |
| 4 | 安其拉 | 0 |
| 5 | 白起 | 1 |
| 6 | 不知火舞 | 0 |
| 7 | 妲己 | 0 |
| 8 | 狄仁杰 | 1 |
| 9 | 小乔 | 0 |
| 10 | 闵月 | 0 |
| 16 | 李白 | 1 |
| 17 | 吕布 | 1 |
| 18 | 嬴政 | 1 |
| 19 | 王昭君 | 0 |
+----+----------+--------+
12 rows in set
mysql> select * from students where id<>8;
+----+----------+--------+
| ID | name | gender |
+----+----------+--------+
| 3 | 诸葛亮 | 1 |
| 4 | 安其拉 | 0 |
| 5 | 白起 | 1 |
| 6 | 不知火舞 | 0 |
| 7 | 妲己 | 0 |
| 9 | 小乔 | 0 |
| 10 | 闵月 | 0 |
| 16 | 李白 | 1 |
| 17 | 吕布 | 1 |
| 18 | 嬴政 | 1 |
| 19 | 王昭君 | 0 |
+----+----------+--------+
11 rows in set
的同学信息
比较运算符(1)
案例:查询名字叫诸葛亮的同学信息
mysql> select * from students where name='诸葛亮';
+----+--------+--------+
| ID | name | gender |
+----+--------+--------+
| 3 | 诸葛亮 | 1 |
+----+--------+--------+
1 row in set
逻辑运算符(1)
案例:查询家在香港的男同学
mysql> select * from students where hometown='香港' and gender=0;
+----+----------+--------+----------+
| ID | name | gender | hometown |
+----+----------+--------+----------+
| 4 | 安其拉 | 0 | 香港 |
| 6 | 不知火舞 | 0 | 香港 |
| 7 | 妲己 | 0 | 香港 |
| 9 | 小乔 | 0 | 香港 |
+----+----------+--------+----------+
4 rows in set
逻辑运算符(2)
案例:查询性别为女生或者家住广州的
mysql> select * from students where hometown='广州' or gender=1;
+----+--------+--------+----------+
| ID | name | gender | hometown |
+----+--------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 5 | 白起 | 1 | 香港 |
| 8 | 狄仁杰 | 1 | 香港 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
+----+--------+--------+----------+
8 rows in set
案例:查询除了id=2的同学信息
mysql> select * from students where not id=5;
+----+----------+--------+----------+
| ID | name | gender | hometown |
+----+----------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 4 | 安其拉 | 0 | 香港 |
| 6 | 不知火舞 | 0 | 香港 |
| 7 | 妲己 | 0 | 香港 |
| 8 | 狄仁杰 | 1 | 香港 |
| 9 | 小乔 | 0 | 香港 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
+----+----------+--------+----------+
11 rows in set
模糊查询
like 表示模糊查询
% 表示任意多个字符
mysql> select * from students where hometown like '%州';
+----+--------+--------+----------+
| ID | name | gender | hometown |
+----+--------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
+----+--------+--------+----------+
6 rows in set
_ 表示一个字符
rlike 可以匹配正则
mysql> select * from students where hometown rlike '.*州';
+----+--------+--------+----------+
| ID | name | gender | hometown |
+----+--------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
+----+--------+--------+----------+
6 rows in set
in 包含在里面的,in 用法匹配括号里面的,符合就返回结果集中
mysql> select * from students where id in (16,17,19);
+----+--------+--------+----------+
| ID | name | gender | hometown |
+----+--------+--------+----------+
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
+----+--------+--------+----------+
3 rows in set
如果需要匹配%本身,那么则需要使用%%
between查询
between and 表示一段区间
mysql> update students set hometown='香港' where id between 5 and 9;
Query OK, 4 rows affected
Rows matched: 5 Changed: 4 Warnings: 0
mysql> select * from students;
+----+----------+--------+----------+
| ID | name | gender | hometown |
+----+----------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 4 | 安其拉 | 0 | 香港 |
| 5 | 白起 | 1 | 香港 |
| 6 | 不知火舞 | 0 | 香港 |
| 7 | 妲己 | 0 | 香港 |
| 8 | 狄仁杰 | 1 | 香港 |
| 9 | 小乔 | 0 | 香港 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
+----+----------+--------+----------+
12 rows in set
2.条件查询(下)
null值判断
先插入几条数据hometown为null值的。
mysql> insert into students values(0,'张飞',0,null),(0,'貂蝉',1,null);
Query OK, 2 rows affected
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from students;
+----+----------+--------+----------+
| ID | name | gender | hometown |
+----+----------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 4 | 安其拉 | 0 | 香港 |
| 5 | 白起 | 1 | 香港 |
| 6 | 不知火舞 | 0 | 香港 |
| 7 | 妲己 | 0 | 香港 |
| 8 | 狄仁杰 | 1 | 香港 |
| 9 | 小乔 | 0 | 香港 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
| 20 | 张飞 | 0 | NULL |
| 21 | 貂蝉 | 1 | NULL |
+----+----------+--------+----------+
14 rows in set
mysql> select * from students where hometown=null;
Empty set
直接用hometown=null并不能得到结果,在mysql中null表示空。
如果要查询为null值的应该是使用is
mysql> select * from students where hometown is null;
+----+------+--------+----------+
| ID | name | gender | hometown |
+----+------+--------+----------+
| 20 | 张飞 | 0 | NULL |
| 21 | 貂蝉 | 1 | NULL |
+----+------+--------+----------+
2 rows in set
排序
order by 字段 [desc/asc]
desc 表示降序(从大到小排序)
asc 默认排序规则,表示升序(从小到大排序)
mysql> select * from students order by id desc;
+----+----------+--------+----------+
| ID | name | gender | hometown |
+----+----------+--------+----------+
| 23 | 李昭 | 1 | 0 |
| 22 | 刘备 | 0 | 0 |
| 21 | 貂蝉 | 1 | NULL |
| 20 | 张飞 | 0 | NULL |
| 19 | 王昭君 | 0 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 10 | 闵月 | 0 | 广州 |
| 9 | 小乔 | 0 | 香港 |
| 8 | 狄仁杰 | 1 | 香港 |
| 7 | 妲己 | 0 | 香港 |
| 6 | 不知火舞 | 0 | 香港 |
| 5 | 白起 | 1 | 香港 |
| 4 | 安其拉 | 0 | 香港 |
| 3 | 诸葛亮 | 1 | 广州 |
+----+----------+--------+----------+
16 rows in set
mysql> select * from students order by id asc;
+----+----------+--------+----------+
| ID | name | gender | hometown |
+----+----------+--------+----------+
| 3 | 诸葛亮 | 1 | 广州 |
| 4 | 安其拉 | 0 | 香港 |
| 5 | 白起 | 1 | 香港 |
| 6 | 不知火舞 | 0 | 香港 |
| 7 | 妲己 | 0 | 香港 |
| 8 | 狄仁杰 | 1 | 香港 |
| 9 | 小乔 | 0 | 香港 |
| 10 | 闵月 | 0 | 广州 |
| 16 | 李白 | 1 | 广州 |
| 17 | 吕布 | 1 | 广州 |
| 18 | 嬴政 | 1 | 广州 |
| 19 | 王昭君 | 0 | 广州 |
| 20 | 张飞 | 0 | NULL |
| 21 | 貂蝉 | 1 | NULL |
| 22 | 刘备 | 0 | 0 |
| 23 | 李昭 | 1 | 0 |
+----+----------+--------+----------+
16 rows in set
3.聚合函数(上)
聚合函数概念
聚合函数主要是为了快速得到结果,经常使用的几个聚合函数
常见函数列表
count 统计行数、max 计算最大值、min 计算最小值、数学函数、sum 求和、avg 求平均数、round 函数、时间函数、substr函数
count函数
查询学生表中一共有多少人
mysql> select count(*) from students;
+----------+
| count(*) |
+----------+
| 16 |
+----------+
1 row in set
max函数
查询这一列中的最大值
查询学生表中id最大的学生
mysql> select max(id) from students;
+---------+
| max(id) |
+---------+
| 23 |
+---------+
1 row in set
min函数
表示查询这一列中的最小值
查询students中id最小值
mysql> select min(id) from students;
+---------+
| min(id) |
+---------+
| 3 |
+---------+
1 row in set
数学函数(1)
MOD(N,M)% 取模 ,即求余数
mysql> select mod(234,10);
+-------------+
| mod(234,10) |
+-------------+
| 4 |
+-------------+
1 row in set
FLOOR(X)向下取整
mysql> select floor(1.23);
+-------------+
| floor(1.23) |
+-------------+
| 1 |
+-------------+
1 row in set
mysql> select floor(1.53);
+-------------+
| floor(1.53) |
+-------------+
| 1 |
+-------------+
1 row in set
数学函数(2)
CEILING(X)向上取整
mysql> select ceiling(1.23);
+---------------+
| ceiling(1.23) |
+---------------+
| 2 |
+---------------+
1 row in set
mysql> select seiling(-1.23);
1305 - FUNCTION study.seiling does not exist
mysql> select ceiling(-1.23);
+----------------+
| ceiling(-1.23) |
+----------------+
| -1 |
+----------------+
1 row in set
mysql>
ROUND(X,D)四舍五入到最近的整数
mysql> select round(-1.23);
+--------------+
| round(-1.23) |
+--------------+
| -1 |
+--------------+
1 row in set
mysql> select round(1.23);
+-------------+
| round(1.23) |
+-------------+
| 1 |
+-------------+
1 row in set
mysql> select round(1.23,1);
+---------------+
| round(1.23,1) |
+---------------+
| 1.2 |
+---------------+
1 row in set
4.聚合函数(下)
avg 求平均数
查询students表中的id的平均数,求平均数之后默认保留了4位小数
mysql> select avg(id) from students;
+---------+
| avg(id) |
+---------+
| 13.0000 |
+---------+
1 row in set
round函数
round(decimal,num) #decimal小数,num保留位数
时间函数
SELECT NOW()显示当前日期及时间
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2021-11-12 14:00:12 |
+---------------------+
1 row in set
CURDATE()当前日期
mysql> select curdate();
+------------+
| curdate() |
+------------+
| 2021-11-12 |
+------------+
1 row in set
CURTIME()当前时间
mysql> select curtime();
+-----------+
| curtime() |
+-----------+
| 14:02:43 |
+-----------+
1 row in set
字符串函数
mysql substr() 函数
用法:substr(string, start, length);
string为字符串;start为起始位置;length为长度。
注意:mysql中的start是从1开始的。
mysql> select substr('mysql',2,3);
+---------------------+
| substr('mysql',2,3) |
+---------------------+
| ysq |
+---------------------+
1 row in set
left(str,len)函数
返回字符串str的最左面len个字符
mysql> select left('mysql',3);
+-----------------+
| left('mysql',3) |
+-----------------+
| mys |
+-----------------+
1 row in set
right(str,len)
返回字符串str的最右面len个字符。
mysql> select right('mysql',3);
+------------------+
| right('mysql',3) |
+------------------+
| sql |
+------------------+
1 row in set
5.分组与分页
分组查询
group by 字段 # 以xx字段作为分组依据分组
注意:分组后分组依据会显示在结果集,其他列不会出现
如:统计男生,女生分别有多少人
mysql> select gender,count(*) from students group by gender;
+--------+----------+
| gender | count(*) |
+--------+----------+
| 0 | 8 |
| 1 | 8 |
+--------+----------+
2 rows in set
as 取别名
上面的例子,在统计人数的时候结果集中显示的是count(*)这个有时候我们并不知道他代表的是什么,如何改成有语义的命名
mysql> select gender,count(*) as '人数' from students group by gender;
+--------+------+
| gender | 人数 |
+--------+------+
| 0 | 8 |
| 1 | 8 |
+--------+------+
2 rows in set
分组后条件筛选
分组后不能使用where做条件过滤,需要一个使用新的having函数,用where会报错,需要用having
mysql> select gender,count(*) as '人数' from students group by gender where gender=0;
1064 - 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 gender=0' at line 1
mysql> select gender as '性别',count(*) as '人数' from students group by gender having gender=0;
+------+------+
| 性别 | 人数 |
+------+------+
| 0 | 8 |
+------+------+
1 row in set
where与having的区别
where用户from之后的条件过滤
having用在分组之后的条件过滤,两个功能是一样的,只是作用的位置不一样
limit分页
分页的原因:如果数据量很大的话,一次性将所有数据查询出来,不仅不方便查看而且耗费传输带宽。那么就使用到了分页功能,一次只查询一页的数据,如:
select * from students limit start,count; #start从第几条数据开始,count表示获取几条数据
mysql> select * from students limit 0,4;
+----+----------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+----------+--------+-----+----------+----------+
| 3 | 诸葛亮 | 1 | 15 | 广州 | 1 |
| 4 | 安其拉 | 0 | 12 | 香港 | 1 |
| 5 | 白起 | 1 | 14 | 香港 | 1 |
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 |
+----+----------+--------+-----+----------+----------+
4 rows in set
mysql> select * from students limit 4,4;
+----+--------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+--------+--------+-----+----------+----------+
| 7 | 妲己 | 0 | 13 | 香港 | 1 |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 |
| 9 | 小乔 | 0 | 15 | 香港 | 1 |
| 10 | 闵月 | 0 | 16 | 广州 | 1 |
+----+--------+--------+-----+----------+----------+
4 rows in set
mysql> select * from students limit 8,4;
+----+--------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+--------+--------+-----+----------+----------+
| 16 | 李白 | 1 | 12 | 广州 | 2 |
| 17 | 吕布 | 1 | 14 | 广州 | 2 |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 |
| 19 | 王昭君 | 0 | 15 | 广州 | 2 |
+----+--------+--------+-----+----------+----------+
4 rows in set
mysql> select * from students limit 12,4;
+----+------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+------+--------+-----+----------+----------+
| 20 | 张飞 | 0 | 15 | NULL | 2 |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 |
| 22 | 刘备 | 0 | 14 | 0 | 2 |
| 23 | 李昭 | 1 | 16 | 0 | 2 |
+----+------+--------+-----+----------+----------+
4 rows in set
实例:每页显示3条数据,要求获取第3页的数据
6.连接查询
连接查询
新需求:给students表中的学生分下班,新加一个class_id字段,保存班级id,之前已经有一个class表已经保存了班级信息了,如:
alter table students add class_id int default null;
id小于15分到1班,大于等于分到2班,如:
update students set class_id = 1 where id < 15;
update students set class_id = 2 where id >=15;
mysql> alter table students add class_id int default null;
Query OK, 16 rows affected
Records: 16 Duplicates: 0 Warnings: 0
mysql> select * from students;
+----+----------+--------+----------+----------+
| ID | name | gender | hometown | class_id |
+----+----------+--------+----------+----------+
| 3 | 诸葛亮 | 1 | 广州 | NULL |
| 4 | 安其拉 | 0 | 香港 | NULL |
| 5 | 白起 | 1 | 香港 | NULL |
| 6 | 不知火舞 | 0 | 香港 | NULL |
| 7 | 妲己 | 0 | 香港 | NULL |
| 8 | 狄仁杰 | 1 | 香港 | NULL |
| 9 | 小乔 | 0 | 香港 | NULL |
| 10 | 闵月 | 0 | 广州 | NULL |
| 16 | 李白 | 1 | 广州 | NULL |
| 17 | 吕布 | 1 | 广州 | NULL |
| 18 | 嬴政 | 1 | 广州 | NULL |
| 19 | 王昭君 | 0 | 广州 | NULL |
| 20 | 张飞 | 0 | NULL | NULL |
| 21 | 貂蝉 | 1 | NULL | NULL |
| 22 | 刘备 | 0 | 0 | NULL |
| 23 | 李昭 | 1 | 0 | NULL |
+----+----------+--------+----------+----------+
16 rows in set
mysql> update students set class_id=1 where id<15;
Query OK, 8 rows affected
Rows matched: 8 Changed: 8 Warnings: 0
mysql> update students set class_id=2 where id>=15;
Query OK, 8 rows affected
Rows matched: 8 Changed: 8 Warnings: 0
mysql> select * from students;
+----+----------+--------+----------+----------+
| ID | name | gender | hometown | class_id |
+----+----------+--------+----------+----------+
| 3 | 诸葛亮 | 1 | 广州 | 1 |
| 4 | 安其拉 | 0 | 香港 | 1 |
| 5 | 白起 | 1 | 香港 | 1 |
| 6 | 不知火舞 | 0 | 香港 | 1 |
| 7 | 妲己 | 0 | 香港 | 1 |
| 8 | 狄仁杰 | 1 | 香港 | 1 |
| 9 | 小乔 | 0 | 香港 | 1 |
| 10 | 闵月 | 0 | 广州 | 1 |
| 16 | 李白 | 1 | 广州 | 2 |
| 17 | 吕布 | 1 | 广州 | 2 |
| 18 | 嬴政 | 1 | 广州 | 2 |
| 19 | 王昭君 | 0 | 广州 | 2 |
| 20 | 张飞 | 0 | NULL | 2 |
| 21 | 貂蝉 | 1 | NULL | 2 |
| 22 | 刘备 | 0 | 0 | 2 |
| 23 | 李昭 | 1 | 0 | 2 |
+----+----------+--------+----------+----------+
16 rows in set
内连接查询:查询的结果为两个表匹配到的数据,两个表都能匹配上的数据将返回给结果集
select * from 表1 inner join 表2 on 表1.列=表2.列;
使用内连接查询学生表和班级表
mysql> select * from students inner join class on students.class_id=class.id;
+----+----------+--------+----------+----------+----+---------+--------+
| ID | name | gender | hometown | class_id | id | name | delete |
+----+----------+--------+----------+----------+----+---------+--------+
| 3 | 诸葛亮 | 1 | 广州 | 1 | 1 | python1 | NULL |
| 4 | 安其拉 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 5 | 白起 | 1 | 香港 | 1 | 1 | python1 | NULL |
| 6 | 不知火舞 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 7 | 妲己 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 8 | 狄仁杰 | 1 | 香港 | 1 | 1 | python1 | NULL |
| 9 | 小乔 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 10 | 闵月 | 0 | 广州 | 1 | 1 | python1 | NULL |
| 16 | 李白 | 1 | 广州 | 2 | 2 | python2 | NULL |
| 17 | 吕布 | 1 | 广州 | 2 | 2 | python2 | NULL |
| 18 | 嬴政 | 1 | 广州 | 2 | 2 | python2 | NULL |
| 19 | 王昭君 | 0 | 广州 | 2 | 2 | python2 | NULL |
| 20 | 张飞 | 0 | NULL | 2 | 2 | python2 | NULL |
| 21 | 貂蝉 | 1 | NULL | 2 | 2 | python2 | NULL |
| 22 | 刘备 | 0 | 0 | 2 | 2 | python2 | NULL |
| 23 | 李昭 | 1 | 0 | 2 | 2 | python2 | NULL |
+----+----------+--------+----------+----------+----+---------+--------+
16 rows in set
在连接查询的时候需要多次用到表名,如果表名过长可以使用as给表取别名
右连接查询:查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充
select * from 表1 right join 表2 on 表1.列=表2.列;
使右连接查询学生表和班级表
mysql> select * from students as s right join class as c on s.class_id=c.id;
+------+----------+--------+------+----------+----------+----+---------+--------+
| ID | name | gender | age | hometown | class_id | id | name | delete |
+------+----------+--------+------+----------+----------+----+---------+--------+
| 3 | 诸葛亮 | 1 | 15 | 广州 | 1 | 1 | python1 | NULL |
| 4 | 安其拉 | 0 | 12 | 香港 | 1 | 1 | python1 | NULL |
| 5 | 白起 | 1 | 14 | 香港 | 1 | 1 | python1 | NULL |
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 | 1 | python1 | NULL |
| 7 | 妲己 | 0 | 13 | 香港 | 1 | 1 | python1 | NULL |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 | 1 | python1 | NULL |
| 9 | 小乔 | 0 | 15 | 香港 | 1 | 1 | python1 | NULL |
| 10 | 闵月 | 0 | 16 | 广州 | 1 | 1 | python1 | NULL |
| 16 | 李白 | 1 | 12 | 广州 | 2 | 2 | python2 | NULL |
| 17 | 吕布 | 1 | 14 | 广州 | 2 | 2 | python2 | NULL |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 | 2 | python2 | NULL |
| 19 | 王昭君 | 0 | 15 | 广州 | 2 | 2 | python2 | NULL |
| 20 | 张飞 | 0 | 15 | NULL | 2 | 2 | python2 | NULL |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 | 2 | python2 | NULL |
| 22 | 刘备 | 0 | 14 | 0 | 2 | 2 | python2 | NULL |
| 23 | 李昭 | 1 | 16 | 0 | 2 | 2 | python2 | NULL |
| NULL | NULL | NULL | NULL | NULL | NULL | 3 | python3 | NULL |
+------+----------+--------+------+----------+----------+----+---------+--------+
17 rows in set
左连接查询:查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充
select * from 表1 left join 表2 on 表1.列=表2.列;
mysql> select * from students as s left join class as c on s.class_id=c.id;
+----+----------+--------+------+----------+----------+------+---------+--------+
| ID | name | gender | age | hometown | class_id | id | name | delete |
+----+----------+--------+------+----------+----------+------+---------+--------+
| 3 | 诸葛亮 | 1 | 15 | 广州 | 1 | 1 | python1 | NULL |
| 4 | 安其拉 | 0 | 12 | 香港 | 1 | 1 | python1 | NULL |
| 5 | 白起 | 1 | 14 | 香港 | 1 | 1 | python1 | NULL |
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 | 1 | python1 | NULL |
| 7 | 妲己 | 0 | 13 | 香港 | 1 | 1 | python1 | NULL |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 | 1 | python1 | NULL |
| 9 | 小乔 | 0 | 15 | 香港 | 1 | 1 | python1 | NULL |
| 10 | 闵月 | 0 | 16 | 广州 | 1 | 1 | python1 | NULL |
| 16 | 李白 | 1 | 12 | 广州 | 2 | 2 | python2 | NULL |
| 17 | 吕布 | 1 | 14 | 广州 | 2 | 2 | python2 | NULL |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 | 2 | python2 | NULL |
| 19 | 王昭君 | 0 | 15 | 广州 | 2 | 2 | python2 | NULL |
| 20 | 张飞 | 0 | 15 | NULL | 2 | 2 | python2 | NULL |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 | 2 | python2 | NULL |
| 22 | 刘备 | 0 | 14 | 0 | 2 | 2 | python2 | NULL |
| 23 | 李昭 | 1 | 16 | 0 | 2 | 2 | python2 | NULL |
| 24 | 赵信 | NULL | NULL | 广州 | NULL | NULL | NULL | NULL |
+----+----------+--------+------+----------+----------+------+---------+--------+
17 rows in set
案例
1、查询学生姓名以及对应班级名称
mysql> select s.name,c.name from students as s inner join class as c on s.class_id=c.id;
+----------+---------+
| name | name |
+----------+---------+
| 诸葛亮 | python1 |
| 安其拉 | python1 |
| 白起 | python1 |
| 不知火舞 | python1 |
| 妲己 | python1 |
| 狄仁杰 | python1 |
| 小乔 | python1 |
| 闵月 | python1 |
| 李白 | python2 |
| 吕布 | python2 |
| 嬴政 | python2 |
| 王昭君 | python2 |
| 张飞 | python2 |
| 貂蝉 | python2 |
| 刘备 | python2 |
| 李昭 | python2 |
+----------+---------+
16 rows in set
备注:students和class表中都有name字段,在显示结果集的时候需要指定表
2、查询python1班所有学生的个人信息和班级信息
select * from students as s inner join class as c on s.class_id=c.id where class_id=1;
mysql> select * from students as s inner join class as c on s.class_id=c.id where class_id=1;
+----+----------+--------+----------+----------+----+---------+--------+
| ID | name | gender | hometown | class_id | id | name | delete |
+----+----------+--------+----------+----------+----+---------+--------+
| 3 | 诸葛亮 | 1 | 广州 | 1 | 1 | python1 | NULL |
| 4 | 安其拉 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 5 | 白起 | 1 | 香港 | 1 | 1 | python1 | NULL |
| 6 | 不知火舞 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 7 | 妲己 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 8 | 狄仁杰 | 1 | 香港 | 1 | 1 | python1 | NULL |
| 9 | 小乔 | 0 | 香港 | 1 | 1 | python1 | NULL |
| 10 | 闵月 | 0 | 广州 | 1 | 1 | python1 | NULL |
+----+----------+--------+----------+----------+----+---------+--------+
8 rows in set
7.子查询
子查询的概念
在一个select语句中嵌入了另外一个select语句,嵌入的这个select语句就是子查询语句。
子查询是辅助主查询的,充当数据源,或者充当条件。子查询是一条独立的语句,即使单独拿出子查询也是可以正常执行的
备注:为方便下面演示:在students表中再加一列年龄age,将学生的年龄补充完整
子查询四种类型
1.标量子查询
2.列级子查询
3.行级子查询
4.表级子查询
标量子查询
子查询返回一行一列的数据,称之为标量子查询
查询学生年龄小于平均年龄的学生信息
子查询语句先查出平均年龄:select avg(age) from students;
select * from students where age < (select avg(age) from students);
mysql> select avg(age) from students;
+----------+
| avg(age) |
+----------+
| 14.1875 |
+----------+
1 row in set
mysql> select * from students where age <(select avg(age) from students);
+----+--------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+--------+--------+-----+----------+----------+
| 4 | 安其拉 | 0 | 12 | 香港 | 1 |
| 5 | 白起 | 1 | 14 | 香港 | 1 |
| 7 | 妲己 | 0 | 13 | 香港 | 1 |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 |
| 16 | 李白 | 1 | 12 | 广州 | 2 |
| 17 | 吕布 | 1 | 14 | 广州 | 2 |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 |
| 22 | 刘备 | 0 | 14 | 0 | 2 |
+----+--------+--------+-----+----------+----------+
9 rows in set
列级子查询
子查询返回的是一列多行的数据,称之为列级子查询
查询class表中已经安排学生的班级信息
select class_id from students 返回的是python1和python2
mysql> select * from class where id in (select class_id from students);
+----+---------+--------+
| id | name | delete |
+----+---------+--------+
| 1 | python1 | NULL |
| 2 | python2 | NULL |
+----+---------+--------+
2 rows in set
备注:可用于子查询的关键字有4个(in、all、any、some)
in: 符合列子查询里面一个
any、some:功能相同,表示任意一个如: where 列 = any(列子查询)
all:等于里面所有,如:where 列 = all(列子查询)
查找2班级的年龄大于1班级的所有同学年龄
mysql> select * from students where class_id=2 and age>all(select age from students where class_id=1);
+----+------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+------+--------+-----+----------+----------+
| 16 | 李白 | 1 | 18 | 广州 | 2 |
| 18 | 嬴政 | 1 | 20 | 广州 | 2 |
+----+------+--------+-----+----------+----------+
2 rows in set
行级子查询
子查询返回的是一行多列,称之为行级子查询
查询一班同学中年龄最大的同学信息,单独使用子查询这条语句查的结果可以看出结果集是一行多列。嵌套到主查询后将查出一班同学中年龄最大的同学信息
mysql> select class_id,max(age) from students where class_id=1;
+----------+----------+
| class_id | max(age) |
+----------+----------+
| 1 | 16 |
+----------+----------+
1 row in set
mysql> select * from students where (class_id,age)=(select class_id,max(age) from students where class_id=1);
+----+----------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+----------+--------+-----+----------+----------+
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 |
| 10 | 闵月 | 0 | 16 | 广州 | 1 |
+----+----------+--------+-----+----------+----------+
2 rows in set
表级子查询
子查询返回多行多列,称之为表级子查询
查询学生信息对应班级名称,子查询返回的数据充当数据源,再进行过滤。
select t1.name,t1.class_name from (select s.*,c.name as class_name from students as s inner join class as c on s.class_id =c.id) as t1;
mysql> select t1.xs as '学生姓名',t1.bj as 班级名称 from (select b1.name as xs,b2.name as bj from students as b1 inner join class b2 on b1.class_id=b2.id) as t1;
+----------+----------+
| 学生姓名 | 班级名称 |
+----------+----------+
| 诸葛亮 | python1 |
| 安其拉 | python1 |
| 白起 | python1 |
| 不知火舞 | python1 |
| 妲己 | python1 |
| 狄仁杰 | python1 |
| 小乔 | python1 |
| 闵月 | python1 |
| 李白 | python2 |
| 吕布 | python2 |
| 嬴政 | python2 |
| 王昭君 | python2 |
| 张飞 | python2 |
| 貂蝉 | python2 |
| 刘备 | python2 |
| 李昭 | python2 |
+----------+----------+
16 rows in set
8.保存查询结果
保存查询结果(1)
语句格式:insert into 表名 (列1,列2) select ..... #这个方法可以将查询的结果直接保存到表里
新建一个表用来保存查询结果,学生id,名字,班级,年龄
mysql> create table info(
-> id int unsigned auto_increment primary key not null,
-> name varchar(10) not null,
-> class_name varchar(10) not null,
-> age int(100) unsigned
-> );
Query OK, 0 rows affected
mysql> desc info;
+------------+-------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(10) | NO | | NULL | |
| class_name | varchar(10) | NO | | NULL | |
| age | int(100) unsigned | YES | | NULL | |
+------------+-------------------+------+-----+---------+----------------+
4 rows in set
全列插入,将查询结果插入到info表。
mysql> insert into info
-> select s.id,s.name,c.name as class_name,age from
-> students as s inner join class as c on s.class_id=c.id;
Query OK, 16 rows affected
Records: 16 Duplicates: 0 Warnings: 0
mysql> select * from info;
+----+----------+------------+-----+
| id | name | class_name | age |
+----+----------+------------+-----+
| 3 | 诸葛亮 | python1 | 15 |
| 4 | 安其拉 | python1 | 12 |
| 5 | 白起 | python1 | 14 |
| 6 | 不知火舞 | python1 | 16 |
| 7 | 妲己 | python1 | 13 |
| 8 | 狄仁杰 | python1 | 14 |
| 9 | 小乔 | python1 | 15 |
| 10 | 闵月 | python1 | 16 |
| 16 | 李白 | python2 | 12 |
| 17 | 吕布 | python2 | 14 |
| 18 | 嬴政 | python2 | 13 |
| 19 | 王昭君 | python2 | 15 |
| 20 | 张飞 | python2 | 15 |
| 21 | 貂蝉 | python2 | 13 |
| 22 | 刘备 | python2 | 14 |
| 23 | 李昭 | python2 | 16 |
+----+----------+------------+-----+
16 rows in set
保存查询结果(2)
指定列插入,约束条件为not null的必须插入,其他可用为null的列自动使用null填充
mysql> insert into info (name,class_name)
-> select s.name,c.name as class_name from students as s inner join class as c on s.class_id=c.id;
Query OK, 16 rows affected
Records: 16 Duplicates: 0 Warnings: 0
mysql> select * from info;
+----+----------+------------+------+
| id | name | class_name | age |
+----+----------+------------+------+
| 3 | 诸葛亮 | python1 | 15 |
| 4 | 安其拉 | python1 | 12 |
| 5 | 白起 | python1 | 14 |
| 6 | 不知火舞 | python1 | 16 |
| 7 | 妲己 | python1 | 13 |
| 8 | 狄仁杰 | python1 | 14 |
| 9 | 小乔 | python1 | 15 |
| 10 | 闵月 | python1 | 16 |
| 16 | 李白 | python2 | 12 |
| 17 | 吕布 | python2 | 14 |
| 18 | 嬴政 | python2 | 13 |
| 19 | 王昭君 | python2 | 15 |
| 20 | 张飞 | python2 | 15 |
| 21 | 貂蝉 | python2 | 13 |
| 22 | 刘备 | python2 | 14 |
| 23 | 李昭 | python2 | 16 |
| 24 | 诸葛亮 | python1 | NULL |
| 25 | 安其拉 | python1 | NULL |
| 26 | 白起 | python1 | NULL |
| 27 | 不知火舞 | python1 | NULL |
| 28 | 妲己 | python1 | NULL |
| 29 | 狄仁杰 | python1 | NULL |
| 30 | 小乔 | python1 | NULL |
| 31 | 闵月 | python1 | NULL |
| 32 | 李白 | python2 | NULL |
| 33 | 吕布 | python2 | NULL |
| 34 | 嬴政 | python2 | NULL |
| 35 | 王昭君 | python2 | NULL |
| 36 | 张飞 | python2 | NULL |
| 37 | 貂蝉 | python2 | NULL |
| 38 | 刘备 | python2 | NULL |
| 39 | 李昭 | python2 | NULL |
+----+----------+------------+------+
32 rows in set
合并查询
1.union all 将两次查询的结果集合并到一起显示
2.union 将两个查询的结果集先去重后合并到一起显示
union all
mysql> select * from students union all select * from students;
+----+----------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+----------+--------+-----+----------+----------+
| 3 | 诸葛亮 | 1 | 15 | 广州 | 1 |
| 4 | 安其拉 | 0 | 12 | 香港 | 1 |
| 5 | 白起 | 1 | 14 | 香港 | 1 |
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 |
| 7 | 妲己 | 0 | 13 | 香港 | 1 |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 |
| 9 | 小乔 | 0 | 15 | 香港 | 1 |
| 10 | 闵月 | 0 | 16 | 广州 | 1 |
| 16 | 李白 | 1 | 12 | 广州 | 2 |
| 17 | 吕布 | 1 | 14 | 广州 | 2 |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 |
| 19 | 王昭君 | 0 | 15 | 广州 | 2 |
| 20 | 张飞 | 0 | 15 | NULL | 2 |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 |
| 22 | 刘备 | 0 | 14 | 0 | 2 |
| 23 | 李昭 | 1 | 16 | 0 | 2 |
| 3 | 诸葛亮 | 1 | 15 | 广州 | 1 |
| 4 | 安其拉 | 0 | 12 | 香港 | 1 |
| 5 | 白起 | 1 | 14 | 香港 | 1 |
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 |
| 7 | 妲己 | 0 | 13 | 香港 | 1 |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 |
| 9 | 小乔 | 0 | 15 | 香港 | 1 |
| 10 | 闵月 | 0 | 16 | 广州 | 1 |
| 16 | 李白 | 1 | 12 | 广州 | 2 |
| 17 | 吕布 | 1 | 14 | 广州 | 2 |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 |
| 19 | 王昭君 | 0 | 15 | 广州 | 2 |
| 20 | 张飞 | 0 | 15 | NULL | 2 |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 |
| 22 | 刘备 | 0 | 14 | 0 | 2 |
| 23 | 李昭 | 1 | 16 | 0 | 2 |
+----+----------+--------+-----+----------+----------+
32 rows in set
union 去重后合并
mysql> select * from students union select * from students;
+----+----------+--------+-----+----------+----------+
| ID | name | gender | age | hometown | class_id |
+----+----------+--------+-----+----------+----------+
| 3 | 诸葛亮 | 1 | 15 | 广州 | 1 |
| 4 | 安其拉 | 0 | 12 | 香港 | 1 |
| 5 | 白起 | 1 | 14 | 香港 | 1 |
| 6 | 不知火舞 | 0 | 16 | 香港 | 1 |
| 7 | 妲己 | 0 | 13 | 香港 | 1 |
| 8 | 狄仁杰 | 1 | 14 | 香港 | 1 |
| 9 | 小乔 | 0 | 15 | 香港 | 1 |
| 10 | 闵月 | 0 | 16 | 广州 | 1 |
| 16 | 李白 | 1 | 12 | 广州 | 2 |
| 17 | 吕布 | 1 | 14 | 广州 | 2 |
| 18 | 嬴政 | 1 | 13 | 广州 | 2 |
| 19 | 王昭君 | 0 | 15 | 广州 | 2 |
| 20 | 张飞 | 0 | 15 | NULL | 2 |
| 21 | 貂蝉 | 1 | 13 | NULL | 2 |
| 22 | 刘备 | 0 | 14 | 0 | 2 |
| 23 | 李昭 | 1 | 16 | 0 | 2 |
+----+----------+--------+-----+----------+----------+
16 rows in set
小结
Linux文件查找与编辑器使用
条件查询(上)
(条件查询、in查询、between查询)
条件查询(下)
(null值判断、排序)
函数(上)
(count函数、max函数、min 函数、数学函数)
聚合函数(下)
(avg函数、round函数 、时间函数、substr函数)
分组与分页
(分组、别名、分组条件筛选、where与 having的区别、limit分页)
连接查询
(mysq三种连接查询、案例)
子查询
(标量子查询、列级子查询、行级子查询、表级子查询)
保存查询结果
(保存查询结果、union、union all)
课后实操题
1、创建一个名为Mydb的数据库,编码格式为utf-8,在Mydb库中创建tb_student学生表.课程表 tb_course. 选课表 tb_score 在表中随便插入一些数据
mysql> create table tb_student(
-> stuid int not null comment'学号',
-> sname varchar(20) not null comment '学生姓名',
-> gender bit default 1 comment '性别',
-> birth date not null comment '出生日期',
-> addr varchar(255) default '' comment '籍贯',
-> collid int not null comment '所属学院编号',
-> primary key (stuid)
-> );
Query OK, 0 rows affected
mysql> desc tb_student;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| stuid | int(11) | NO | PRI | NULL | |
| sname | varchar(20) | NO | | NULL | |
| gender | bit(1) | YES | | b'1' | |
| birth | date | NO | | NULL | |
| addr | varchar(255) | YES | | | |
| collid | int(11) | NO | | NULL | |
+--------+--------------+------+-----+---------+-------+
6 rows in set
mysql> create table tb_coure(
-> couid int not null comment '课程编号',
-> cname varchar(50) not null comment '课程名称',
-> credit tinyint not null comment '学分',
-> teaid int not null comment '教师工号',
-> primary key (couid)
-> );
Query OK, 0 rows affected
mysql> desc tb_coure;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| couid | int(11) | NO | PRI | NULL | |
| cname | varchar(50) | NO | | NULL | |
| credit | tinyint(4) | NO | | NULL | |
| teaid | int(11) | NO | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set
mysql> create table tb_score(
-> scid int not null auto_increment comment '选课编号',
-> sid int not null comment '学号',
-> cid int not null comment '课程编号',
-> seldate date comment '选课时间日期',
-> mark decimal(4,1) comment '考试成绩',
-> primary key (scid)
-> );
Query OK, 0 rows affected
mysql> desc tb_score;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| scid | int(11) | NO | PRI | NULL | auto_increment |
| sid | int(11) | NO | | NULL | |
| cid | int(11) | NO | | NULL | |
| seldate | date | YES | | NULL | |
| mark | decimal(4,1) | YES | | NULL | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set
查询所有80后学生的姓名、性别和出生日期(筛选)
mysql> select sname as '姓名',if(gender,'男','女') as '性别',birth as '出生日期' from tb_student where birth between '1980-1-1' and '1989-12-31';
+----------+------+------------+
| 姓名 | 性别 | 出生日期 |
+----------+------+------------+
| 汪洋 | 男 | 1983-06-08 |
| 欧阳先锋 | 男 | 1986-09-08 |
+----------+------+------------+
2 rows in set
查询名字由4个中文字符的学生学号和姓名(运算+函数)
mysql> select sname as '姓名',stuid as '学号' from tb_student where length(sname)/2=4;
+----------+-----------+
| 姓名 | 学号 |
+----------+-----------+
| 欧阳先锋 | 103321005 |
+----------+-----------+
1 row in set
查询名字中有”文“字或“先”字的学生的姓名(模糊)
mysql> select sname as '姓名',stuid as '学号' from tb_student where sname rlike '.*文' or sname rlike '.*先';
+----------+-----------+
| 姓名 | 学号 |
+----------+-----------+
| 杨文杰 | 103321001 |
| 欧阳先锋 | 103321005 |
+----------+-----------+
2 rows in set
查询学生选课的所有日期(去重)
mysql> select distinct seldate as 选课日期 from tb_score;
+------------+
| 选课日期 |
+------------+
| 2021-11-12 |
| 2021-11-08 |
+------------+
2 rows in set
查询男学生的姓名和生日按年龄从大到小排列(排序)
mysql> select sname as 姓名,birth as 生日 from tb_student where gender=1 order by birth desc;
+----------+------------+
| 姓名 | 生日 |
+----------+------------+
| 何伟 | 1995-08-04 |
| 杨文杰 | 1995-01-06 |
| 欧阳先锋 | 1986-09-08 |
| 汪洋 | 1983-06-08 |
+----------+------------+
4 rows in set
查询每个学生的学号和平均成绩(分组和聚合函数)
mysql> select sid as 学号,avg(mark) as 平均成绩 from tb_score group by sid;
+-----------+----------+
| 学号 | 平均成绩 |
+-----------+----------+
| 103321001 | 92 |
| 103321002 | 95 |
| 103321003 | 90 |
+-----------+----------+
3 rows in set
查询选了两门以上的课程的学生姓名(子查询/分组条件/集合运算)
mysql> select sname as 姓名 from tb_student where stuid in
(select sid as 学号 from tb_score group by sid having count(sid)>=2);
+--------+
| 姓名 |
+--------+
| 杨文杰 |
+--------+
1 row in set
查询选课学生的姓名和平均成绩(子查询和连接查询)
mysql> select sname as 姓名,avgMark as 平均分 from tb_student t1 inner join
(select sid,avg(mark) as avgMark from tb_score group by sid) as t2 on t1.stuid=t2.sid;
+--------+--------+
| 姓名 | 平均分 |
+--------+--------+
| 杨文杰 | 89 |
| 何玲峰 | 95 |
| 何伟 | 90 |
+--------+--------+
3 rows in set
查询每个学生的姓名和选课数量(左外连接和子查询)
mysql> select sname as 姓名,ifnull(total,0) as 选课数量 from tb_student t1 left join (select sid,count(sid) as total from tb_score group by sid) t2 on t1.stuid=t2.sid;
+----------+----------+
| 姓名 | 选课数量 |
+----------+----------+
| 杨文杰 | 2 |
| 何玲峰 | 1 |
| 何伟 | 1 |
| 汪洋 | 0 |
| 欧阳先锋 | 0 |
+----------+----------+
5 rows in set