数据库多表查询

在SM数据库中进行以下操作:

1.查询选修了数据库的学生的学号;

select sno 
from sc,course 
where course.cname='数据库' and course.cno=sc.cno

2.查询数据库成绩不及格的学生名单(输出学号、姓名、成绩);

select student.sno,sname,score 
from sc,course,student
where course.cname='数据库' and course.cno=sc.cno and sc.score<60 and sc.sno=student.sno

这里我漏了course.cno=sc.cno导致了错误,课程号没有连接导致输出全部不及格的信息

3.使用内连接查询每个学生及其选修课程情况;

select * 
from sc inner join student 
on student.sno=sc.sno

在这里插入图片描述
可以看到sc与student内连接,student每一行都与sc连接,他们的共有属性是sno,所以根据sno来匹配

4.使用左连接查询查询每个学生及其选修课程情况;

select * 
from sc left join student 
on student.sno=sc.sno

5.使用右连接查询查询每个学生及其选修课程情况;

select * 
from student right outer join sc 
on student.sno=sc.sno

不可以向上面一样直接改right,sc right join student
这样sc做主表

6.在表Teacher中,查询职工张三的上级领导信息;

select * from teacher t1 where t1.tno =( select t2.mgr from teacher t2 where tname='张三')

可以用=也可以用in,因为子查询只有一个值就可以用in

7.使用IN查询修读课程名为数据库的所有学生的学号和姓名;

select student.sno,student.sname 
		from student 
		where student.sno in(select sc.sno 
									from sc 
									where sc.cno in(select course.cno 
														from course 
														where course.cname='数据库'))

最内层从course表查询数据库的cno,再从sc表查询选修了数据库的sno,再从student 表查询sname,sno

不使用in查询,使用连接查询也可以
select student.sno,sname from student,sc,course where sc.sno=student.sno and course.cno=sc.cno and cname=‘数据库’

8.使用EXISTS查询所有选修了001号课程的学生的姓名;

select sname 
		from student 
		where EXISTS(select * 
							from sc 
							where student.sno=sc.sno and sc.cno='001')

student表每一行都与sc表匹配观察是否有满足student.sno=sc.sno and sc.cno=‘001’

形象一点来说就是有一类student的人,他找到sc这类人,student有sno等属性但是每个人的属性值不一样,每一个student人与sc作对接,每次询问你跟我的sno是不是一样的,并且当前这个sc人的cno属性是001的,如果都满足就返回student人的sname属性值

9.使用NOT EXISTS查询未选修了001号课程的学生的姓名;

select sname 
	from student 
	where not EXISTS(select * 
							from sc 
							where student.sno=sc.sno and sc.cno='001')

内部有选择001课程的则返回false,没选择001课程 的返回true。
not exists通常用在题目出现否定词的情况,比如未选择。。。

10.使用NOT EXISTS查询选修了课程学分为4的全部课程的学生的姓名;
在这里插入图片描述

思路:一个学生如果他至少有一门四学分课程没有选修,那么他在课程表里就会存在与选课表的非交集,我们姑且称之为“未选所有四学分课程学生名单子集”,它由内层的not
exists选出。这个内层父子关联存在子查询选出课程表里与选课表的非交集,最内层选课表sc的课程号cno、学号sno分别与第二层父表course课程的cno、最外层父表studen学生表的sno进行对等连接,不存在对等的记录即为非交集,从而筛选出“未选四学分所有课程学生名单子集”。

11.统计教职工的总人数、最高工资、最少工资、平均工资;

select count(*) as 总人数,MAX(sal) as 最大工资,min(sal) as 最少工资,avg(sal) as 平均工资 
from Teacher

12.查询选修两门课程以上的学生学号;

select distinct s1.sno 
from sc s1,sc s2 
where s1.sno=s2.sno and s1.cno!=s2.cno 

思路:在sc表查询两次,s1.sno=s2.sno and s1.cno!=s2.cno,在每个学生对于选课不同就说明选修了两门课以上
记得去重因为每个学生选了大于2门课的记录,不去重就会输出多个sno。

select sno 
from sc group by sno having count(*)>1

先对sc表的sno进行分组,分组结果如果大于1说明选课数大于2

13.查询选修了三门课程的学生学号;

select sno 
from sc group by sno having count(*)=3

14.使用分组查询选修了所有课程的学生学号、姓名。
在这里插入图片描述

思路:在SC表中某个学生选修的课程数等于Course表中课程总数,首先查出course表一共有多少门课select count(*)
from course,根据Sno分组,统计每个学生选修了几门课程。如果等于Course表课程的总数,就是我们要找的Sno

15.在选修课001中,使用ALL查询比学号00001和学号00004的成绩都低的学生学号;
在这里插入图片描述
常见误区:在这里插入图片描述
这里经常会写成and,因为根据题意查询比学号00001和学号00004的成绩都低,但是一个人成绩不能同时低于两个数字,所以用or

16.在选修课001中,使用ANY查询比学号00001或学号00004的成绩低的学生学号;
在这里插入图片描述

17.在选修课001中,查询比平均成绩低的学生的学号;
在这里插入图片描述

18.给出所有课程(不包括001这门课程)都及格的学生的平均成绩,按平均成绩降序排序;

19.找出SC表中score值最小的行,不能使用min函数;
20.找出SC表中score值最小的行,允许使用min函数;
21.找出SC表中score值重复的行;
22.把SC表的第5行记录选出来。