作为MySQL数据库的初学者,多表查询的知识点多,内容复杂,很令人头大。这篇文章作为总结,以案例的形式,供大家理解和记忆。
目录
概述
一、内连接
案例:查询每个学生的姓名和选课的名称
二、外连接
案例:1.查询学生表的所有数据和对应的选课名称(左查询)
案例:2.查询选课表所有数据和对应的学生名称(右查询)
三、自连接
案例:查询每个学生和对应组长的姓名(没有组长的也要查询)
四、标量子查询
案例:1.查询选MySQL课程的所有学生的全部信息
案例:2.查询比张三年龄大的所有学生的全部信息
五、列子查询
案例:查询比选C语言学生的年龄都要大的学生
六、行子查询
案例:查询与小明年龄和分数相同的学生信息
七、表子查询
案例:查询年龄大于18岁,的学生信息及选课信息
多表查询主要分以下两个方面:
一、连接查询
1.内连接
2.外连接
3.自连接
二、子查询
1.标量子查询
2.列子查询
3.行子查询
4.表子查询
我们就用这样的两张学生选课信息表格作为数据
id | name | age | score | group leader id | classid |
1 | 张三 | 18 | 88 | null | 1 |
2 | 李四 | 18 | 77 | null | 1 |
3 | 王五 | 17 | 70 | 1 | 2 |
4 | 小明 | 19 | 92 | 2 | 2 |
5 | 小红 | 20 | 52 | 2 | 3 |
6 | 小刚 | 19 | 92 | 1 | null |
id | name |
1 | MySQL |
2 | C语言 |
3 | Java |
4 | Python |
内连接有两种表现形式:
隐式内连接:
select 字段列表 from 表1, 表2 where 条件;
显式内连接:(中括号内的内容可省略)
select 字段列表 from 表1 [inner] join 表2 on 条件;
内连接查询的是两个表格交集的部分。
两者不同主要在于隐式内连接用“ , ”连接两个表格,条件用where ;显式内连接用“ join ”连接两个表格,条件用on。
分析:以学生的classid与课程的id相等为条件查询(两表的交集部分),并列出student.name和class.name字段
1.隐式内连接:
select s.name,c.name from student s,class c where s.classid=c.id;
2.显式内连接:
select s.name,c.name from student s join class c on s.classid=c.id;
运行结果:
注:小刚没有选课,所以他与选课表无交集,故没有显示。
外连接主要分为两种:左外连接、右外连接。
左外连接:
selcet 字段列表 from 表1 left [outer] join 表2 on 条件;
查询的是表1(左表)的所有数据包含表1和表2交集部分的数据
右外连接:
selcet 字段列表 from 表1 right [outer] join 表2 on 条件;
查询的是表1(左表)的所有数据包含表1和表2交集部分的数据
两者在字面意思上就可以区分,左外连接查询的是左表全部和交集部分,右外连接查询的是右表全部和交集部分,两者只需记住左外连接即可(右外连接也可),实际应用时交换左外连接中两表顺序即可达到右外连接效果。
select s.name,c.name from student s left join class c on s.classid = c.id;
运行结果
select s.name,c.name from student s right join class c on s.classid = c.id;
运行结果
可见,外连接可以将两表中非交集的部分查询出来。小刚没有选课,他对应的选课名称就是null
Python没有人选,学生姓名也是null。
自连接语法
select 字段列表 from 表A 别名A join 表A 别名B on 条件;
自连接查询,是同一张表用两个别名查询,可以是内连接查询,也可以是外连接查询
分析:组长也是学生,那么表格中的group leader id字段代表的就是组长的id,例如王五的group leader id为1,张三的id为1,那么张三就是王五的组长。张三李四无group leader id,二人为组长。
select A.name,B .name from student A left join student B on A.`group leader id`=B.id
注:group为关键字所以group leader id要用单引号引起来。
运行结果
这个案例中,自连接用的是左外连接,因为没有组长的也要查询。这里的自连接可以理解为两张相同的表以左外连接的查询方式进行查询。
标量子查询返回的结果是单个值(数字、字符串、日期等)
常用操作符: = , <> , > , >= , < , <=
可以理解为嵌套。
select * from student where student.classid=
(select class.id from class where class.name ='MySQL');
代码分析:
1. select class.id from class where class.name ='MySQL'查询并返回出MySQL课程的id
2. select * from student where student.classid=返回的id值
3. 将两个式子嵌套在一起,并加括号
运行结果
select * from student s where s.age>
(select s.age from student s where s.name='张三');
运行结果
子查询返回的结果是一列(可以是多行)
常用操作符: in , not in , any(满足一个) , some(满足一个) , all(满足全部)
分析:第一步,查询出选C语言的id;第二部,查询出选C语言学生的年龄。第二步,查询出所有比选C语言学生的年龄都要大的学生。
select *from student s where age>all
(select s.age from student s where s.classid=
(select c.id from class c where c.name='C语言'));
代码分析:
1. select c.id from class c where c.name='C语言'
查询出选C语言的id
2. select s.age from student s where s.classid=
查询出选C语言学生的年龄
3. select *from student s where age>all
询出所有比选C语言学生的年龄都要大的学生。all表示比每一个都大
最后嵌套在一起
运行结果
行子查询返回的结果是一行(可以是多列)
常用操作符:= , <> , in , not in
select *from student where (age,score)=(select age,score from student where name='小明');
这个比较好理解,注意括号内的对应关系
运行结果
返回的结果是多行多列
select *from (select * from student where age>18) s left join class on class.id=s.classid;
代码分析:
1. select * from student where age>18
查询年龄大于18岁的学生信息,作为一张表并起别名
2. select *from (select * from student where age>18) s left join class on class.id=s.classid;
以这张大于18岁的学生信息表作为一张表,查询选课信息
运行结果