带有EXISTS谓词的子查询

来源:互联网 发布:电子签名生成器软件 编辑:程序博客网 时间:2024/06/06 06:58

EXISTS代表存在量词 。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。

例如:三个表:

student(sno,sname,ssex,sage,sdept)(学号,姓名,性别,年龄,专业)

course(cno,cname,cpno,ccredit)(课程号,课程名,选修课号,学分)

sc(sno,cno,grade)(学号,课程号,成绩)

 

 1、 查询所有选修了1号课程的学生姓名。

本题涉及student和sc表。可以在student中一次取得每个元组的sno值,用此值去检查sc表。若sc表存在这样的元组,其sno值等于此student.sno值,并且其cno='1',则取此student.sname送入结果表。将此想法写成sql语句是:

select sname from student

where exists (

   select *

    from sc

    where sno=student.sno and cno='1'

  );

使用存在量词exists后,若内层查询结果非空,则外层的where子句返回真值,否则返回假值。由于exists引出的子查询,其目标列表达式通常用*,因为带exists的子查询只返回真值或假值,给出列名无实际意义。

本例中子查询的查询条件依赖于外层父查询的某个属性值(在本例中是student的sno值),因此也是相关子查询。这个相关子查询的处理过程是:首先取外层查询中(student)表的第一个元组,根据它与内层查询相关的属性值(sno值)处理内层查询,若where子句返回值为真,则取外层查询中该元组的sname放入结果表;然后再取(student)表的下一个元组;重复这一过程,直至外层(student)表全部检查完为止。

        与exists谓词相对应的是not exists谓词。使用存在量词not exists后,若内层查询结果为空,则外层的where子句返回真值,否则返回假值。

 

2、查询没有选修1号课程的学生姓名

   select sname from student

   where not exists (

    select * from sc sno=student.sno and cno='1'

 );

一些带exists或not exists 谓词的子查询不能被其他形式的子查询等价替换,但所有带in谓词、比较运算符、any和all谓词的子查询都能用带exists谓词的子查询等价替换。

 

        由于带EXISTS量词的相关子查询只关心内层查询是否有返回值,并不需要查具体值,因此其效率并不一定低于不相关子查询,有时是高效的方法。

SQL中没有全称量词

SQL中也没有蕴含逻辑运算,可以用谓词演算将其转换为:

1、查询选修了全部课程的学生姓名

2、查询至少选修了学生95002选修的全部课程的学生号码

 

1、没有全称量词,将其转换为等价的用存在量词的形式:查询这样的学生,没有一门课是他不选的。

select sname

from student

where not exists(

       select *

       from course

       where not exist(

              select *

              from sc

              where sc.sno = student.sno

              and cno = course.cno

       )

)

2、本查询用逻辑蕴含表达:查询学号为x的学生,对所有的课程y,只要95002学生选了课程y,则x也选了y。形式化表示如下

用p表示:学生95002选了课程y

用q表示:学生x选了课程y

 

转换为等价形式:

 

它表示的语义为:不存在这样的课程y,学生95002选了,而学生x没有选,sql如下:

select distinct sno

from sc scx

where not exists(

       select *

       from sc scy

       where sno='95002'

       and not exist(

              select *

              from scz

              where scz.sno = scx.sno

              and scz.cno=scy.cno))  

 

1.用EXISTS/NOT EXISTS实现全称量词

SQL语言中没有全称量词"(For all),可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:

              " (x)PÛØ ($x(P))   :含义 " (x)P表示个体域里的所有个体都有性质P。Ø ($x(P)) 表示不存在着个体域中的个体没有性质P。

  查询选修了全部课程的学生姓名。

        SELECTSname

         FROM Student

         WHERE NOT EXISTS

            (SELECT *

              FROM Course

              WHERE NOT EXISTS

                 (SELECT *

                  FROM SC

                  WHERE Sno= Student.Sno

                     AND Cno= Course.Cno);

 

2.用EXISTS/NOT EXISTS实现逻辑蕴函

SQL语言中没有蕴函(Implication)逻辑运算可以利用谓词演算将逻辑蕴函谓词等价转换为:

                  p®qÛØp∨q

 查询至少选修了学生95002选修的全部课程的学生号码。

解题思路:

用逻辑蕴函表达:查询学号为x的学生,对所有的课程y,只要95002学生选修了课程y,则x也选修了y。

形式化表示:

          用P表示谓词 “学生95002选修了课程y”

          用q表示谓词 “学生x选修了课程y”

则上述查询为:" (y) p® q

等价变换:

            " (y) p® qÛØ ($y (Ø (p®q ))

                      ÛØ ($y (Ø(Øp∨ q))

                      ÛØ$y(p∧Øq)

变换后语义:不存在这样的课程y,学生95002选修了y,而学生x没有选。

用NOT EXISTS谓词表示:    

    SELECT DISTINCTSno

         FROM SC SCX

         WHERE NOT EXISTS

               (SELECT *

                FROM SC SCY

                WHERE SCY.Sno = ' 95002 ' AND

                    NOT EXISTS

                         (SELECT *

                          FROM SC SCZ

                          WHERESCZ.Sno=SCX.Sno AND

                                          SCZ.Cno=SCY.Cno));

 

 

 
  含义 " (x)P表示个体域里的所有个体都有性质P。Ø ($x(P)) 表示不存在着个体域中的个体没有性质P。
0 0