EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False
【例3.60】
select Sname
from TEST.Student
where exists (
select *
from TEST.SC
where Sno=Student.Sno and Cno='1'
)
select *
from TEST.SC
select *
from TEST.Student
父查询中迭代元组,进入子查询如果满足其中的条件就会返回true,否则false
【例3.61】
select Sname
from TEST.Student
where not exists (
select *
from TEST.SC
where Sno=Student.Sno and Cno='1'
)
实质与【3.60】同,不再赘述
【例3.62】
select Sname
from TEST.Student
where not exists(
select *
from TEST.Course
where not exists(
select *
from TEST.SC
where Sno=Student.Sno
and Cno=Course.Cno
)
)
为了更简单的理解这个例子,看接下来的代码
--实例1
select *
from TEST.Course
where not exists(
select *
from TEST.SC
where Sno='2018'
and Cno=Course.Cno
)
--
select *
from TEST.Course
where not exists(
select *
from TEST.SC
where Sno='2019'
and Cno=Course.Cno
)
select *
from TEST.SC
在exists 如果子句里面的由select形成的新的关系是至少有一个元组,可以认为将会返回true,否则返回false。可以看到学号为2018 的同学 选择了1 ,2 3课程(总共只有3门课),因此2018 对应的course表就是空的,由于最外层是not exists 因此 2018 这个同学符合要求。对于学号为2019 的同学,对应的course关系不为空。select *from TEST.Course (…)这段代码代表的是一个学生没有选的课的信息。2019 这个同学没有选择3课程。可以看出在course这个关系中课程是按照一个一个的元组进入到最内层进行选择,因此在返回的时候会返回这个元组是否存在,就是true ,false。与数据结构中的二重循环类似,当内层的所有的元组迭代完成之后才会返回。其实整个例子可以解读为存在一个同学,这个同学学没有 未选的课程。直接翻译就是选择了所有的课程。
根据上面的解读,代码的逻辑结构不再那么难懂,再看这个例子:
--实例2
select Sname
from TEST.Student
where not exists(
select Cno
from TEST.Course
where not exists(
select Sno
from TEST.SC
where Sno=Student.Sno
and Cno=Course.Cno
)
)
这个例子中select 后面的只有一个属性,结果应该是与select* 一致的,这就说明了exists 只在乎true,false实例1中对于学号为‘2019’的这个同学 1课程选了所以从第三层返回第二层的时候没有这个记录,(因为是not )返回false,同理对于3课程返回的是true(因为没有选),因此这名同学从第二层返回到第三层中就是true,这个true是course关系中各个元组返回后的bool类型的并。这也就解释了从第二层返回到第一层中false的同学是符合的,那么从第三层返回第二层false 的必然是选了所有课程。
【例3.63】
select distinct Sno
from TEST.SC x
where x.Sno<>'2019'and not exists (
select *
from TEST.SC y
where y.Sno='2019' and not exists (
select *
from TEST.SC z
where z.Sno=x.Sno and z.Cno= y.Cno
)
)
使用distinct 是因为学生很有可能选了不止一次的课,先假设x,与y,z关系不同,x 中的一个元组对应一个y表,如果想与‘2019’这位同学比较,还需要一个表z,所以对于SC表总共使用了三次。
为了简要说明看这个例子:
select Cno
from TEST.SC y
where y.Sno='2019' and not exists (--指明‘2019’这个同学
select *
from TEST.SC z
where z.Sno='2020' and z.Cno= y.Cno
)
这个例子较为简单,select 的是学号为‘2020’的同学没有选择2019同学所选的课程的序号。同理如果去掉not 就是2020与2019同学都选了的课程号。借鉴【例3.62】最外层加上的not exists的意思就是不存在2019选了2020 没有选。对于这个例子大致的分析同【例3.62】不再赘述
【例3.64】
这个例子我做了修改,改为性别为男,年龄不大于19 的交集
首先引入知识点:
集合查询
(1)union 并
(2)intersect 交
(3)except 差
注意:参与集合操作的关系列数相同,属性值相同
select *
from TEST.Student
where Ssex='m'
union
select *
from TEST.Student
where Sage<19
--这个union 的操作类似于distinct
--想要重复的使用union all
【例3.65】
select Sno
from TEST.SC
where Cno='1'
union
select Sno
from TEST.SC
where Cno='2'
这个列数都是相同的,可以union
【例3.66】
这个例子做了修改,改为性别是m
select *
from TEST.Student
where Ssex='m'
intersect
select *
from TEST.Student
where Sage<=19
这个例子其实是对同一个关系进行的操作 因此可以直接select相关条件
【3.67】
select Sno
from TEST.SC
where Cno='1'
intersect
select Sno
from TEST.SC
where Cno='2'
这个例子也可以用嵌套查询:在选择了2课程 中选择1同学
select Sno
from TEST.SC
where Cno='1' and Sno in (
select Sno
from TEST.SC
where Cno='2'
)
【例3.68】
这个例子做了修改改为性别与年龄的交集
select *
from TEST.Student
where Ssex='m'
except
select *
from TEST.Student
where Sage<19
【例3.57】(plus)
引入知识点:派生表
select Sno,Cno
from TEST.SC,(
select Sno,avg(Grade)
from TEST.SC
group by Sno
)
as avg_sc(a_sno,a_grade)
where SC.Sno=a_sno and SC.Grade >=a_grade
【例3.60】(plus)
select Student.Sno,Sname
from TEST.Student,(select Sno
from TEST.SC
where Cno='1'
)
as x
where Student.Sno=x.Sno
--这个例子同样使用了派生表,如果新的关系中含有新的属性,需要将关系重新声明
--如【例3.57】(plus)
select总结
1.格式:
一般的格式是:
select [all|distinct ]<目标列表达式>[别名] ....
from <表名视图名>[别名]
[where <条件>]
[group by <列名>[having <条件表达式>]]
[order by <列名>[asc|desc]]
--where作用于分组之前
--having 作用于之后
上述是完整的select语句,where作用于group by 之前,having作用于之后。
select Sno
from TEST.SC
where Cno='1'
group by Sno having sum(Grade)>10
order by Sno desc
再看一个例子(错误的示范)
select *
from TEST.SC
where Cno='1'
group by Sno having sum(Grade)>10
order by Sno desc
这个例子中使用group by 之后select 的列属性要么是分组的依据,要么是在聚合函数中。可以这样理解使用聚集函数之后对于SNO 属性 后面只有一个Sum(Grade)对应
select Sno,Grade
from TEST.SC
group by Sno having sum(Grade)>10
order by Sno desc
因此这个例子也是一个错误的示范。
2 查询条件
比较:= < > >= <= != <> !> !<
确定范围: between and, not between and
字符匹配: like , not like (模糊匹配)
空值: NULL is not null
多条件: or and
给一个例子:
select Sno
from TEST.Student
group by Sno having sum(Sage) >10 and max(Sage)<=20
order by Sno desc
--不再演示where
3嵌套查询:
(1)使用in (没有 not in )
(2)使用exists (子查询返回的只是true false) ,多于连接一起使用
(3)带谓词的查询
关于all ,any 在select使用在【例3.58】