连接查询
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>
等值与非等值连接查询
等值连接:连接运算符为=
自然连接:在等值连接中把目标列中重复的属性列去掉
自身连接:一个表与其自己进行连接
[例 3.49] 查询每个学生及其选修课程的情况
select student.*,sc.*
from student,sc
where student.sno=sc.sno
查询结果:
[3.50] 对[例 3.49]用自然连接完成。
select student.sno,sname,ssex,sage,sdept,cno,grade
from student,sc
where student.sno = sc.sno;
对于存在多个表中的属性名,需要指出其中一个表,不然会报错:
在等值连接中把目标列中重复的属性列去掉,查询结果:
[3.51]查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
where后写条件:本题目的条件分为两个方面:2号课程,成绩在90分以上。但前提是需要先将student和sc表中满足条件的元组等值连接。
select student.sno,sname
from student,sc
where student.sno = sc.sno
and sc.cno='2' and sc.grade > 90;
查询结果:
[3.52]查询每一门课的间接先修课(即先修课的先修课)
自身链接:对于同一个表多次使用,因此要对该表进行命名加以区分。
select first_table.cno,second_table.cpno
from course first_table,course second_table
where first_table.cpno = second_table.cno;
查询结果:
外连接:外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出。
对外连接的理解可以参考以下博客:
[3.53]改写[例 3.49]查询每个学生及其选修课程的情况
select student.sno,sname,ssex,sage,sdept,cno,grade
from student left outer join sc on (student.sno=sc.sno);
于3.49对比,可以看出后者显示了所有元组,即选修课为NULL的也显示了。
[3.54]查询每个学生的学号、姓名、选修的课程名及成绩
select student.sno,sname,cname,grade
from student,sc,course
where student.sno = sc.sno
and sc.cno = course.cno;
多表连接中需要分清哪些属性是多个表共有的并且指明。
查询结果:
嵌套查询
[3.55]查询与“刘晨”在同一个系学习的学生。
方法一:
① 先通过以下代码找出刘晨所在的系别。
select sdept
from student
where sname='刘晨'
② 通过已知的系别找出其他学生
select sno,sname,sdept
from student
where sdept = 'cs'
该种方法适合单个查询,但若条件较多的话就不太方便了,因此嵌套查询正是用来解决该种问题的。
方法二:嵌套查询:
select sno,sname,sdept
from student
where sdept in
(select sdept
from student
where sname='刘晨');
除了嵌套查询,我们还可以直接使用连接查询:
select fir.sno,fir.sname,fir.sdept
from student fir,student sec
where sec.sname='刘晨'
and fir.sdept=sec.sdept
最终的结果是相同的。
[3.56]查询选修了课程名为“信息系统”的学生学号和姓名
该题型于上题类似,很容易想到的就是嵌套查询:
方法一:
select student.sno,sname,sc.cno,cname
from student,sc,course
where student.sno=sc.sno
and course.cno = sc.cno
//显示所有选课同学的信息
select sno,sname
from student
where sno in
(select sno
from sc
where cno in(
select cno
from course
where cname='信息系统')
);
除了嵌套查询,我们还可以直接使用连接查询:
方法二:
select student.sno,sname
from student,sc,course
where student.sno=sc.sno
and sc.cno = course.cno
and course.cname='信息系统'
最后的查询结果是一样的。
[3.57]找出每个学生超过他选修课程平均成绩的课程号。
类似两个for循环嵌套,先把里面的算出来,然后在用外面的进行比较筛选。
select * from sc
select sno,cno
from sc x
where grade>=(select avg(grade)
from sc y
where y.sno=x.sno);
查询结果:
[3.58]查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
这个题目感觉有点歧义,当时上课的时候就有这种感觉,后来是想通了。现在再做第一感觉还是别不过来,主要是这个“任意一个”,我理解成了all,也就是前者比后者里面所有人都小,后来想了半天才理解过来,是比任意其中选一个小就行!!!
select sname,sage
from student
where sdept <>'cs'
and sage<any
(select sage
from student
where sdept='cs')
查询结果:
[3.59]查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。
这个题应该是我本来理解的上面的那个题哈哈哈哈,其实是看到了这个题才理解了上面的题想要表达的意思。
select *
from student
select sname,sage
from student
where sage<
(select min(sage)
from student
where sdept='cs')
and sdept<>'cs';
或者
select sname,sage
from student
where sdept <>'cs'
and sage<all
(select sage
from student
where sdept='cs')
转载:https://blog.csdn.net/Freedomhy/article/details/104938629