使用子查询(嵌套查询)
1、查询有一门及格的学生
select * from tbl_student s
where 60 < any(select score from tbl_grade g where s.snum =g.snum);
或
select * from tbl_student s
where 60 < some(select score from tbl_grade g where s.snum = g.snum);
any 、 some 、 all 区别
any表示子查询返回值中的任意一个值(any是等于N个or语句)
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)
)
2、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区别
1、 in 是把外表和内表作 hash 连接
select * from tbl_grade g
where snum in (select snum from tbl_student where sex=‘0’)
2、 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可以按如下思路,否则不好理解:
1、exists子查询是找到即停止并返回true(找到),找不到返回false(找不到)
说明:不要去翻译为存在和不存在,把脑袋搞晕。
2、头脑中建立for循环
3、exists首先执行外层查询,再执行内层查询,与IN相反。
如果not in返回至少一个null,那么not in就返回flase,第一个表的数据行就不会显示。
对于not exists,只是关心是否返回行,因此返回的无论是null还是非null,都是true,只要有数据返回。
使用not in还是not exists,不仅仅是功能上不同,而且在性能上也有很大的不同。NOT IN会骗过子查询中所涉及表的索引。
来源:oschina
链接:https://my.oschina.net/u/2862827/blog/1934810