sql select 练习

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】

发布了15 篇原创文章 · 获赞 12 · 访问量 7046

猜你喜欢

转载自blog.csdn.net/weixin_44724691/article/details/104948223