3.4.2-5 连接、嵌套、集合查询以及基于派生表的查询

第三章完整版->有道云笔记

  • 连接查询

等值与非等值连接查询

连接查询的WHERE子句用来连接两个表的条件称为连接条件连接谓词,一般格式为:

    [<表名1>.] <列名 1><比较运算符> [<表名2>.] <列名 2>

连接运算符为=时,称为等值连接。使用其他运算符称为非等值连接
连接谓词中的列名称为连接字段。连接条件中的各连接字段类型必须是可比的,但名字不必相同。

    /* 查询选修2号课程且成绩在90分以上的所有学生的学号和姓名
       Sname是唯一的,可省略表名前缀,而Sno必须加上表名前缀,避免混淆 */
    SELECT Student.Sno, Sname
    FROM Student, SC
    WHERE Student.Sno = SC.Sno AND          /*  连接谓词 */
            SC.Cno = '2' AND SC.Grade > 90; /*  其他限定条件(选择谓词) */

自身连接

一个表与自己进行连接,要先为表取别名。

    /* 查询每一门课的间接先修课(即先修课的先修课) */
    SELECT FIRST.Cno, SECOND.Cpno
    FROM Course FIRST, Course SECOND
    WHERE FIRST.Cpno = SECOND.Cno;

FIRST表(Course表)

Cno Cname Cpno Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 操作系统 2
7 数据结构 6 4

SECOND表(Course表)

Cno Cname Cpno Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 操作系统 2
7 数据结构 6 4

连接结果:

Cno Cpno
1 7
3 5
5 6

外连接: [<表名1>] LEFT | RIGHT OUTER JOIN [<表名2>] ON 谓词

P55 2.4.2中详解:把悬浮元组也保存在结果关系中,而在其他属性上填空值(NULL)。保留左边关系所有元组为左外连接,保留右边关系中所有元组为右外连接。

例:左外连接,列出每个学生的基本情况及选课情况,若某个学生无选课,SC表属性上填NULL。

    SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
    FROM Student LEFT OUTER JOIN SC ON(Student.Sno = SC.Sno);

多表连接

两个以上的表进行连接。

    /* 查询每个学生的学号、姓名、选修的课程名及成绩 */
    SELECT Student.Sno, Sname, Cname, Grade
    From Student, SC, Course
    WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno;
  • 嵌套查询

一个SELECT-FROM-WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。上层查询块称为外层查询父查询,下层查询块称为内层查询子查询。子查询的SELECT语句中不能使用ORDER BY子句,ORDER BY子句只能对最终查询结果排序。

带有IN谓词的子查询(最常用)

    /* 查询与“刘晨”在同一个系学习的学生
       方法一:嵌套查询-不相关查询
       子查询的查询条件不依赖于父查询,称为不相关子查询 */
    SELECT Sno, Sname, Sdept 
    FROM Student 
    WHERE Sdept IN    /* 内查询结果的是一个值,可以用 = 代替IN */
            (SELECT Sdept
            FROM Student
            WHERE Sname = '刘晨');
    /* 方法二:自身连接 */
    SELECT S1.Sno, S1.Sname, S1.Sdept
    FROM Student S1, Student S2
    WHERE S1.Sdept = S2.Sdept AND S2.Sname = '刘晨'; 

[注]:有些嵌套查询可以用连接运算替代,尽可能采用连接运算

带有比较运算符的子查询

    // 找出每个学生超过他自己选修课程平均成绩的课程号
    // 子查询的查询条件依赖于父查询,称为相关子查询
    SELECT Sno, Cno
    FROM SC x
    WHERE Grade >= (SELECT AVG(Grade)  // 根据x.Sno求出某学生课程的平均成绩
                    FROM SC y
                    WHERE y.Sno = x.Sno);

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

子查询返回多值时,要用ANY或ALL谓词修饰符。

比较运算符+谓词 语义
>ANY 大于子查询结果中的某个值
>ALL 大于子查询结果中的所有值
小于子查询结果中的某个值
小于子查询结果中的所有值
>=ANY 大于等于子查询结果中的某个值
<=ALL 大于等于子查询结果中的所有值
<=ANY 小于等于子查询结果中的某个值
<=ALL 小于等于子查旬结果中的所有值
=ANY 等于子查询结果中的某个值
=ALL 等于子查询结果中的所有值(通常没有实际意义)
!=(或<>)ANY 不等于子查询结果中的某个值
!=(或<>)ALL 不等于子查询结果中的任何一个值
    
    SELECT Sname, Sage
    FROM Student
    WHERE Sage  'CS';

带有EXISTS谓词的子查询

EXISTS代表存在量词,带有EXISTS谓词的子查询不返回任何数据,且产生逻辑真值“true”或逻辑价值“false”。
由EXISTS引出的子查询,其目标列表达式通常都用*

 /* 查询选修了全部课程的学生姓名 */
    SELECT Sname
    FROM Student
    WHERE NOT EXISTS
        (SELECT *
          FROM Course
          WHERE NOT EXISTS
              (SELECT *
                FROM SC
                WHERE Sno = Student.Sno 
                AND Cno = Course.Cno));

[注]:SQL中没有全称量词,但可以把带有全称量词的谓词转换为等价的带有存在量词的谓词,双重否定=>肯定。

  • 集合查询

SELECT语句查询的结果是元组的集合,所以多个SELECT语句的结果可进行集合查询。包括并操作UNION交操作INTERSECT差操作EXCEPT

   /* 查询计算机科学系的学生与年龄不大于19岁的学生的交集 */
   SELECT *
   FROM Student
   WHERE Sdept = 'CS'
   INTERSECT
   SELECT *
   FROM Student
   WHERE Sage <= 19;

[注]:参加集合操作的各查询结果列数、对应项的数据类型必须相同。

  • 基于派生表的查询

子查询也可以出现在FROM子句中,此时子查询生成的临时派生表成为主查询的查询对象。

    /* 找出每个学生超过他自己选修课程平均成绩的课程号 */
    SELECT Sno, Cno
    FROM SC, (SELECT Sno, Avg(Grade) FROM SC GROUP BY Sno)
             AS Avg_sc(avg_sno, avg_grade)
             WHERE SC.Sno = Avg_sc.sno AND SC.Grade >= Avg_sc.avg_grade;
  • SELECT语句的一般格式 P114

你可能感兴趣的:(3.4.2-5 连接、嵌套、集合查询以及基于派生表的查询)