SQL(2)--复杂查询

2018-10-18  本文已影响0人  zealscott

介绍多表查询等复杂SQL语句。

关系数据库的查询结果都是一个结果表(也是关系)

集聚函数

基本语法

例子

GROUP BY 子句

细化聚集函数的作用对象

HAVING短语与WHERE子句的区别:

例子

  1. 求各个课程号及相应的选课人数

       SELECT Cno, COUNT(Sno)
       FROM    SC
       GROUP BY Cno; 
    
  2. 查询选修了3门以上课程的学生学号

     SELECT Sno
         FROM  SC
         GROUP BY Sno
         HAVING  COUNT(*) >3;      
    
  3. 查询平均成绩大于等于90分的学生学号和平均成绩

        SELECT  Sno, AVG(Grade)
        FROM  SC
        GROUP BY Sno
        HAVING AVG(Grade)>=90;
    

    这里只能使用HAVING,不能使用WHERE

ORDER BY子句

例子

  1. 查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列

        SELECT Sno, Grade
        FROM    SC
        WHERE  Cno= ' 3 '
        ORDER BY Grade DESC;
    
  2. 查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列

        SELECT  *
        FROM  Student
        ORDER BY Sdept, Sage DESC;  
    

连接查询

(非)等值连接查询

等值连接:连接运算符为=,这里与Join操作等价。

例子

  1. 查询每个学生及其选修课程的情况

        SELECT  Student.*, SC.*
        FROM     Student, SC
        WHERE  Student.Sno = SC.Sno;
    
  2. 一条SQL语句可以同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的复合条件。

    查询选修2号课程且成绩在90分以上的所有学生的学号和姓名

        SELECT  Student.Sno, Sname
        FROM     Student, SC
        WHERE  Student.Sno=SC.Sno  AND                          
               SC.Cno=' 2 ' AND SC.Grade>90;
    

执行过程

嵌套循环法(NESTED-LOOP)

可以发现,等值连接的复杂度很高,为O(m* n)。

自身连接

例子

  1. 查询每一门课的间接先修课(即先修课的先修课)

     SELECT  FIRST.Cno, SECOND.Cpno
         FROM  Course  FIRST, Course  SECOND
         WHERE FIRST.Cpno = SECOND.Cno;
    

外连接

外连接与普通连接的区别

例子

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

多表连接

两个以上的表进行连接。

MongoDB不提供这种操作:

例子

  1. 查询每个学生的学号、姓名、选修的课程名及成绩

      SELECT Student.Sno, Sname, Cname, Grade
      FROM   Student, SC, Course    /*多表连接*/
      WHERE Student.Sno = SC.Sno 
                   AND SC.Cno = Course.Cno;
    

嵌套查询

带有IN谓词的子查询

  1. 查询与“刘晨”在同一个系学习的学声

    SELECT Sno, Sname, Sdept
             FROM Student
             WHERE Sdept  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 = '刘晨';
    
  2. 查询选修了课程名为“信息系统”的学生学号和姓名

    SELECT Sno,Sname                
         FROM    Student                         
         WHERE Sno  IN
                 (SELECT Sno                    
                  FROM    SC                         
                  WHERE  Cno IN
                         (SELECT Cno             
                           FROM Course           
                           WHERE Cname= '信息系统' )
                  );
    /*用连接查询表示*/
    SELECT Sno,Sname
          FROM    Student,SC,Course
          WHERE   Student.Sno = SC.Sno  AND
                  SC.Cno = Course.Cno AND
                  Course.Cname='信息系统';            
    

带有比较运算符的子查询

例子

  1. 找出每个学生超过他选修课程平均成绩的课程号

    SELECT Sno, Cno
        FROM    SC x
        WHERE Grade >= ( SELECT AVG(Grade) 
                         FROM  SC y
                         WHERE y.Sno = x.Sno );
    /*用连接查询表示*/
    SELECT First.Sno, First.Cno
     FROM SC First JOIN (
         SELECT Sno, AVG(Grade) as A_Grade
            FROM SC
            GROUP BY Sno) SA
            ON First.Sno = SA.Sno
         WHERE First.Grade > SA.A_Grade
    

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

使用ANY或ALL谓词时必须同时使用比较运算

若子查询中不是唯一的,使用ANY/ALL可以使用比较运算符

语义为:

> ANY 大于子查询结果中的某个值

>ALL 大于子查询结果中的所有值

>=ANY 大于等于子查询结果中的某个值

<=ANY 小于等于子查询结果中的某个值

=ANY 等于子查询结果中的某个值

!=(或<>)ALL 不等于子查询结果中的任何一个值

例子

  1. 查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄

    SELECT Sname,Sage
        FROM    Student
        WHERE Sage < ANY ( SELECT  Sage
                           FROM    Student
                           WHERE Sdept= ' CS ')
         AND Sdept <> ‘CS ' ;           /*父查询块中的条件 */
    
    /*用聚集函数实现*/
    
    SELECT Sname,Sage
         FROM   Student
         WHERE Sage < 
                      ( SELECT MAX(Sage)
                         FROM Student
                         WHERE Sdept= 'CS ')
          AND Sdept <> ' CS ';
    
  2. 查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄

    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谓词

例子

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

    思路

    • 本查询涉及StudentSC关系
    • 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 ');
    
  2. 查询没有选修1号课程的学生姓名。

    SELECT Sname
         FROM     Student
         WHERE NOT EXISTS
                       (SELECT *
                        FROM SC
                        WHERE Sno = Student.Sno AND    Cno='1');
    

难点

上一篇下一篇

猜你喜欢

热点阅读