oracle子查询 in exists

徘徊边缘 提交于 2020-03-02 05:25:58

使用子查询(嵌套查询)

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会骗过子查询中所涉及表的索引。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!