数据库-连接查询、嵌套查询、集合查询(二)

2015-07-24 08:12:57 · 作者: · 浏览: 11
C x WHERE Grade >=(SELECT AVG(Grade) FROM SC y WHERE y.Sno=x.Sno);
可能的执行过程: 
1. 从外层查询中取出SC的一个元组x,将元组x的Sno值(200215121)传送给内层查询。
       SELECT AVG(Grade)
       FROM SC y
       WHERE y.Sno='200215121';
2. 执行内层查询,得到值88(近似值),用该值代替内层查询,得到外层查询:
       SELECT Sno, Cno
       FROM  SC x
       WHERE Grade >=88; 
3. 执行这个查询,得到
    (200215121,1)
    (200215121,3) 
4.外层查询取出下一个元组重复做上述1至3步骤,直到外层的SC元组全部处理完毕。结果为:
    (200215121,1)
    (200215121,3)
    (200215122,2)

带有ANY(SOME)或ALL谓词的子查询

谓词语义
ANY:任意一个值
ALL:所有值

需要配合使用比较运算符
> ANY   大于子查询结果中的某个值       
 > ALL  大于子查询结果中的所有值
< ANY   小于子查询结果中的某个值    
< ALL   小于子查询结果中的所有值
>= ANY  大于等于子查询结果中的某个值    
>= ALL  大于等于子查询结果中的所有值
<= ANY  小于等于子查询结果中的某个值    
<= ALL  小于等于子查询结果中的所有值
= ANY   等于子查询结果中的某个值        
=ALL    等于子查询结果中的所有值(通常没有实际意义)
!=(或<>)ANY  不等于子查询结果中的某个值
!=(或<>)ALL  不等于子查询结果中的任何一个值
[例42]  查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄
    SELECT Sname,Sage
    FROM    Student
    WHERE Sage < ANY (SELECT  Sage
                                         FROM    Student
                                         WHERE Sdept= ' CS ')
           AND Sdept <> ‘CS ' ;           /*父查询块中的条件 */
用聚集函数实现[例42] 

    SELECT Sname,Sage
     FROM   Student
     WHERE Sage < 
                             (SELECT MAX(Sage)
                               FROM Student
                               WHERE Sdept= ‘CS ')
           AND Sdept <> ' CS ’;
[例43]  查询其他系中比计算机科学系所有学生年龄都小的学生姓名及年龄。

方法一:用ALL谓词
    SELECT Sname,Sage
    FROM Student
    WHERE Sage < ALL
                           (SELECT Sage
                            FROM Student
                            WHERE Sdept= ' CS ')
           AND Sdept <> ' CS ’;
       方法二:用聚集函数
        SELECT Sname,Sage
        FROM Student
        WHERE Sage < 
                               (SELECT MIN(Sage)
                                FROM Student
                                WHERE Sdept= ' CS ')
              AND Sdept <>' CS ’;

带有EXISTS谓词的子查询

EXISTS谓词
存在量词?
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
若内层查询结果非空,则外层的WHERE子句返回真值
若内层查询结果为空,则外层的WHERE子句返回假值
由EXISTS引出的子查询,其目标列表达式通常都用* ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义 NOT EXISTS谓词
若内层查询结果非空,则外层的WHERE子句返回假值
若内层查询结果为空,则外层的WHERE子句返回真值
[例44]查询所有选修了1号课程的学生姓名。

思路分析:
本查询涉及Student和SC关系
在Student中依次取每个元组的Sno值,用此值去检查SC关系
若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其Cno= '1',则取此Student.Sname送入结果关系
用嵌套查询
     SELECT Sname
     FROM Student
     WHERE EXISTS
                   (SELECT *
                    FROM SC
                    WHERE Sno=Student.Sno AND Cno= ' 1 ');
用连接运算
    SELECT Sname
    FROM Student, SC
    WHERE Student.Sno=SC.Sno AND SC.Cno= '1';
[例45]  查询没有选修1号课程的学生姓名。
     SELECT Sname
     FROM Student
     WHERE NOT EXISTS
                   (SELECT *
                    FROM SC
                    WHERE Sno = Student.Sno AND Cno='1');

不同形式的查询间的替换
一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换
所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换
用EXISTS/NOT EXISTS实现全称量词(难点)
SQL语言中没有全称量词? (For all)
可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:
(?x)P ≡ ? (? x(? P))

例:[例39]查询与“刘晨”在同一个系学习的学生。
       可以用带EXISTS谓词的子查询替换:
     SELECT Sno,Sname,Sdept
     FROM Student S1
      WHERE EXISTS
                 (SELECT *
                     FROM Student S2
                     WHERE S2.Sdept = S1.Sdept AND
                                   S2.Sname = ‘刘晨’);
[例46] 查询选修了全部课程的学生姓名。
        SELECT Sname
        FROM Student
        WHERE NOT EXISTS
                    (SELECT *
                        FROM Course
                        WHERE NOT EXISTS
                                      (SELECT *
                                       FROM SC
                                       WHERE Sno= Student.Sno
                                             AND Cno= Course.Cno
                                       )
                       );
   用EXISTS/NOT EXISTS实现逻辑蕴函(难点)
SQL语言中没有蕴函(Implication)逻辑运算
可以利用谓词演算将逻辑蕴函谓词等价转换为:
                   p ? q ≡ ? p∨q 
 [例47]查询至少选修了学生200215122选修的全部课程的学生号码。
解题思路:
用逻辑蕴函表达:查询学号为x的学生,对所有的课程y,只要200215122学生选修了课程y,则x也选修了y。
形式化表示:
    用P表示谓词 “学生200215122选修了课程y”
    用q表示谓词 “学生x选修了课程y”
    则上述查询为: (?y) p ? q 
用NOT EXISTS谓词表示:     
     SELECT DISTINCT Sno
       FROM SC SCX
       WHERE NOT EXISTS
                     (SELECT *
                      FROM SC SCY
                      WHERE SCY.Sno = ' 200215122 '  AND
                                    NOT EXISTS
                                    (SELECT *
                                     FROM SC SCZ
                                     WHERE SCZ.Sno=SCX.Sno AND
                                                   SCZ.Cno=SCY.Cno));

集合查询

集合操作的种类
并操作UNION
交操作INTERSECT
差操作EXCEPT(MINUS)
参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同

[例48]  查询计算机科学系的学生及年龄不大于19岁的学生。
方法一:
        SELECT *
        FROM Student
        WHERE Sdept= 'CS'
        UNION
        SELECT *
        FROM Student
        WHERE Sage<=19;
UNION:将多个查询结果合并起来时,系统自动去掉重复元组。
UNION ALL:将多个查询结果合并起来时,保留重复元组 
方法二:
       SELECT  DISTINCT  *
        FROM Student
        WHERE Sdept= 'CS'  OR  Sage<=19;
[例50]  查询计算机科学系的学生与年龄不大于19岁的学生的交集

SELECT *
FROM Student
WHERE Sdept='CS' 
INTERSECT
SELECT *
FROM Student
WHERE Sage<=19 
[例50] 实际上就是查询计算机科学系中年龄不大于19岁的学生

        SELECT *
            FROM Student
            WHERE Sdept= 'CS' AND  Sage<=19;
[例51]  查询选修课程1的学生集合与选修课程2的学生集合的交集
     SELECT Sno
    FROM SC
    WHERE Cno=' 1 ' 
    INTERSECT
    SELECT Sno
    FROM SC
    WHERE Cno='2 '
[例51]实际上是查询既选修了课程1又选修了课程2   的学生
        SELECT Sno
          FROM SC
          WHERE