【数据库实验】镶嵌查询

带有IN谓词的子查询

[例 3.55] 查询与“梁一一”在同一个系学习的学生。

这里用的in,如果有两个系里都有这名同学,那么子查询会返回两个值,那么查询的就是这两个系的所有学生。
如果能确定没有重名,即子查询的返回值只有一个学生。那么可以用=。

select *
from student
where Sdept in(
      select Sdept
	  from student
	  where Sname='梁一一');

在这里插入图片描述

[例 3.56]查询选修了课程名为“数据库”的学生学号和姓名
select Sno,Sname
from student
where Sno in(
		     select Sno
			 from sc
			 where Cno in(
							select Cno
							from course
							where Cname='数据库'));

在这里插入图片描述
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询

相关子查询 相当于 循环,每次从外层循环里找出来一个元素,或者说元组,然后在里面的循环里,根据这个元组 ,做一些操作;然后里层循环遍历完,再从外层循环里取下一个元组,一直这样进行下去。

[例 3.57 ]找出每个学生超过他选修课程平均成绩的课程号。
select Sno,Cno
from SC x
where Grade>(
				select AVG(Grade)
				from SC y
				where x.Sno=y.Sno
);

在这里插入图片描述
(下面的代码用到了 基于派生表的查询)

带有比较运算符的子查询

事实上,select返回的是一个集合,刚才用in是集合里可能有好几个数据;这里用 比较运算符(>,<,=,>=,<=,!=或< >)就是得确定 集合只有一个元素。关于例子我们在这个文章的第一题已经说过了,这里不再写。

带有ANY(SOME)或ALL谓词的子查询

any 相当于存在,all相当于所有。所以这个语义就很简单了。我们高中就讲过。
在这里插入图片描述

[例 3.58] 查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
select Sname,Sage
from student
where  Sdept!='cs' AND Sage < ANY(
					select Sage
					from student
					where Sdept='CS'
);

在这里插入图片描述

当然我们可以用 聚集函数 替换any all----第二段代码
(我感觉他们算是一类,any all 以及 聚集函数都是作用在集合上,包括后面的exist,然后返回一个值)

[例 3.59] 查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。
select Sname,Sage
from student
where  Sdept!='cs' AND Sage < ALL(
					select Sage
					from student
					where Sdept='CS'
);

在这里插入图片描述

带有EXISTS谓词的子查询

关于几点:

  1. 只返回true或者false;
  2. 当内层查询里有数据时,为true,否则为false;
  3. 相当于存在量词。
  4. 一般内层查询的列只用*,因为无论写什么,他只返回一个true 或者 false。
  5. not exists 相当于exist取反。
[例 3.60]查询所有选修了1号课程的学生姓名。
select Sname,Sno
from student 
where EXISTS(
		select *
		from SC
		where Sno=student.Sno AND Cno='1'
)

在这里插入图片描述
这里有一个疑问
对比这俩代码

select *
from student
where Sdept in(
      select Sdept
	  from student
	  where Sname='梁一一');

select Sname,Sno
from student 
where EXISTS(
		select *
		from SC
		where Sno=student.Sno AND Cno='1'
)

前者的student是遍历的时候的student,而后者是 普通的那个表(不是正在遍历的时候那个)
我刚开始想的是第一段代码那里,应该加个别名,这样就可以区分是正在遍历的表还是一般那个表。
后来发现这其实是 相关子查询和不相关子查询的区别。

[例 3.61] 查询没有选修1号课程的学生姓名。
select Sname,Sno
from student 
where NOT EXISTS(
		select *
		from SC
		where Sno=student.Sno AND Cno='1'
)

在这里插入图片描述
一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换
所有带IN谓词、比较运算符、ANY和ALL谓词的子查询 都能用带EXISTS谓词的子查询 等价替换

用存在量词实现全称量词(sql中没有全称量词)

在这里插入图片描述

[例 3.62] 查询选修了全部课程的学生姓名。
select Sname
from student
where NOT EXISTS (
					select *
					from course
					where NOT EXISTS(
										select *
										from sc
										where sc.Cno=course.cno AND student.Sno=sc.Sno))

在这里插入图片描述


  这就是个三重循环
  for(auto x:student)
	for(auto y:course)
		for(auto z:SC)
  对于一个学生来说 遍历所有的课程 如果对于某个课程 他有 ,
  那么最内层查询就会返回 数据,因为其谓词是not exits,所以返回f

  如果存在一个课没有选 就会 存在一个t
  只要有一个t 第二层查询(从内向外说)他就返回true 但是 其谓词
  是not exits ,所以他就返回f

  如果全部课都选了  那么最外层循环返回的都是t 加上not 都是f
  都是f再一not 就是t

用EXISTS / NOT EXISTS实现逻辑蕴涵

在这里插入图片描述

[例 3.63]查询至少选修了学生201215131选修的全部课程的学生号码。

在最难的题这 遇到了 SQL SERVER崩溃
在这里插入图片描述

select Sno
from student
where NOT EXISTS(
				select *
				from course,sc
				where  sc.Sno='201215131' AND NOT EXISTS(
														select *
														from sc sc2
														where sc2.Sno=student.Sno AND sc2.Cno=sc.Cno));

在这里插入图片描述

遍历每个学生  每个选课记录
对于某个学生来说
 遍历每个选课记录 如果这个课是31选的 那就看and后面的条件 如果这个学生也选了这个课 就是f 第二层查询总体就是f
 如果存在一个课 31选了 而这个课程没选   第二层查询就是t
 那么第一层就是f

书上最外层循环用的是sc,而我用的是student,那样的话就加个distinct,大同小异吧。

终于补完上周的作业了,前两天考试一直没写。
后面俩例题确实很难,得多写写。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值