使用子查询(嵌套查询)oop
一、查询有一门及格的学生性能
select * from tbl_student s翻译
where 60 < any(select score from tbl_grade g where s.snum =g.snum);排序
或索引
select * from tbl_student shash
where 60 < some(select score from tbl_grade g where s.snum = g.snum);for循环
any 、 some 、 all 区别效率
any表示子查询返回值中的任意一个值(any是等于N个or语句)select
expr>any(单列多行子查询),expr大于子查询中任一返回值, 也就是只要大于子查询最小返回值就能够了循环
some在此表示知足其中一个的意义,是用or串起来的比较从句。 some和any用法意义是同样的。
all表示子查询返回值中的全部值 (all是等于N个And语句)
expr>all(单列多行子查询),expr大于子查询中全部返回值,也就是必需要大于子查询中最大返回值才行
1 、 in 子查询
in 按子查询返回值分为:单行单列、多行单列、单行多列、多行多列
in 按是否与主表链接分为:相关子查询、无关子查询
1.1 、单行单列子查询
查询学生的成绩,要求显示学生的姓名
select (select sname from tbl_student s where s.snum=g.snum) as sname,
(select cname from tbl_course c where c.cnum=g.cnum) as cname,
score
from tbl_grade g
1.2 、多行单列子查询
查询男同窗的成绩
select * from tbl_grade g
where snum in (select snum from tbl_student where sex=‘0’)
1.3 、单行多列或多行多列子查询
查询男同窗的成绩
select * from tbl_grade g where (snum,’0’) in (select snum,sex from tbl_student)
1.4 、检索学全了课程的学生
select * from student s where snum in(
select g.snum from tbl_grade g group by g.snum
having count(*) = (select count(*) from tbl_course)
)
1.5 、检索没学全课程的学生
select * from student s where snum in(
select g.snum from tbl_grade g group by g.snum
having count(*) < (select count(*) from tbl_course)
)
二、exists子查询
只要子查询找到一条记录,结果就是true
2.1 、查询选修过课程的学生
select * from tbl_student s
where exists (select * from tbl_grade where s.snum=g.snum)
2.2 、查询没有选修过 1 号课程的学生的信息
select * from tbl_student s
where not exists
(select * from tbl_grade g where g.cnum=1 and s.snum=g.snum)
2.3 、查询男同窗的成绩
select * from tbl_grade g
where exists (select * from tbl_student s where s.snum=g.snum and sex=‘0’)
2.4 、检索学全了课程的学生
分析:不可能【找不到一门课,这么课找不到成绩】
select s.* from tbl_student s where not exists(
select * from tbl_course c where not exists(
select * from tbl_grade g where g.snum=s.snum and c.cnum=g.cnum
))
2.5 、检索没学全课程的学生
分析:可能【找到 一门课 找不到 成绩】
select s.* from tbl_student s where exists(
select * from tbl_course c where not exists(
select * from tbl_grade g where g.snum=s.snum and c.cnum=g.cnum
))
in和exists区别
一、 in 是把外表和内表做 hash 链接
select * from tbl_grade g
where snum in (select snum from tbl_student where sex=‘0’)
二、 exists 是对外表做 loop 循环,每次 loop 循环再对内表进行查询。
如select * from tbl_grade g
where exists (select * from tbl_student s where s.snum=g.snum and sex=‘0’)
可理解为:
for(g : select * from tbl_grade) {
if(exists(select * from tbl_student s where s.snum=g.snum and sex=‘0’)) {
print g;
}
}
所以:
in:若是内表返回数据量太大,确定生成临时表,并且会进行排序,效率很是低。
所以,适合内表返回数据量较小的状况。
exists:外表确定是循环,若是外表数据量太大,也一样效率低。
所以,适合内表返回数据量多的状况。
使用exists能够按以下思路,不然很差理解:
一、exists子查询是找到即中止并返回true(找到),找不到返回false(找不到)
说明:不要去翻译为存在和不存在,把脑壳搞晕。
二、头脑中创建for循环
三、exists首先执行外层查询,再执行内层查询,与IN相反。
若是not in返回至少一个null,那么not in就返回flase,第一个表的数据行就不会显示。
对于not exists,只是关心是否返回行,所以返回的不管是null仍是非null,都是true,只要有数据返回。
使用not in仍是not exists,不单单是功能上不一样,并且在性能上也有很大的不一样。NOT IN会骗过子查询中所涉及表的索引。