数据库多表查询
在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行记录选出来。