zoukankan      html  css  js  c++  java
  • sql面试-查询选修课程的学生

    首先:

    1 。  EXISTS 子查询找到的提交

                NOT EXISTS 子查询中 找不到的提交

               说明:不要去翻译为存在和不存在,把脑袋搞晕。

      2 。 建立程序循环的概念,这是一个动态的查询过程。如 FOR循环 。

      3 。 Exists执行的流程Exists首先执行外层查询,再执行内存查询,与IN相反。 流程为首先取出外

    层中的第        一  元组, 再执行内层查询,将外层表的第一元组代入,若内层查询为真,即有结果

    时。返回外层表中的第一元 组,接着取出第二元组,执行相同的算法。一直到扫描完外层整表 。

             for(int i =0;  i<>EOFout;i++)

                     {

                         for (int j = 0 ; j<EOFint,j++)

                    }

    然后再来看一个例子: 三张表  学生表student (Sno,Sname),  课程表course (Cno,Cname) 选课表SC

    (Sno,Cno)

    要求查询出 :选修了全部课程的学生姓名

    我的思路:

    首先学生的选课信息存在于SC表中, 要想知道某个学生是否选修了全部课程,至少我们需要知道一共有

    几门课程,这是首要的条件。其次,学生选修了与否,我们又要扫描SC全表,统计出选修了所有课程的

    学生号,最后在STUDENT表中根据学生号打出姓名 。

    语句如下:  (已测试)

    select Sname from student             

     where Sno IN

       (select Sno from SC

       group by Sno //根据Sno分组,统计每个学生选修了几门课程。如果等于course的总数,就是我们要找的Sno

         having count(*) = (select count(*) from course ))    //统计course中共有几门课程

    另一种思路:

    引入:将题目换为 查找学号为 00003 没有选修的科目  

            思路:我们可以将已知学号代入,把每一个科目代入(循环),这将形成1*count(*)种组合。

    将这组成作为条件,一一与SC表种进行比对,找不到匹配的我们提交 。

                     select Cname from course  where

                              not exists               //找不到的组合,提交course

                                   (select * from SC where course.cno = cno and sno = ''00002'')

    //在SC中匹配

    换个题目: 查找没有 没有选修科目的学生姓名

             思路:学号未知 , 科目未知,说明有两个未知变量。应该有两个EXISTS。我们可以扫描

    student 和 course共有 s * c 中组合,将这些组合与SC的每一项进行匹配,注意s*c组合已经包含所

    有可能。如果全部找到 ,就说明已经选修了全部课程。找不到就说明有课程没选修 。再将没选修的的

    提交给上一exists 循环 。若上一exists 不存在的再提交给外循环。

                            select Sname from student

                               where NOT exists        //

                                  (select  * from course

                                   where NOT exists      //不存在的提交给course

                                    (select * from SC where

                                        Sno = student.sno  and cno = Course.Cno))   // 代入两个未知变量

    回头看,就是我们第一个引出的题目:

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

    首先头脑中有三点概念:

        1 。 EXISTS 子查询找到的提交

                NOT EXISTS 子查询中 找不到的提交

               说明:不要去翻译为存在和不存在,把脑袋搞晕。

    2 。 建立程序循环的概念,这是一个动态的查询过程。如 FOR循环 。

    3 。 Exists执行的流程Exists首先执行外层查询,再执行内存查询,与IN相反。 流程为首先取出外

    层中的第一元组, 再执行内层查询,将外层表的第一元组代入,若内层查询为真,即有结果

    时。返回外层表中的第一元 组,接着取出第二元组,执行相同的算法。一直到扫描完外层整表 。

             for(int i =0; i<>EOFout;i++)

                     {

                         for (int j = 0 ; j<EOFin,j++)

                    }

    然后再来看一个例子: 三张表 学生表student (Sno,Sname), 课程表course (Cno,Cname) 选课表SC

    (Sno,Cno)

    要求查询出 :选修了全部课程的学生姓名

    我的思路:

    首先学生的选课信息存在于SC表中, 要想知道某个学生是否选修了全部课程,至少我们需要知道一共有

    几门课程,这是首要的条件。其次,学生选修了与否,我们又要扫描SC全表,统计出选修了所有课程的

    学生号,最后在STUDENT表中根据学生号打出姓名 。

    语句如下: (已测试)

    select Sname from student             

    where Sno IN

       (select Sno from SC

       group by Sno //根据Sno分组,统计每个学生选修了几门课程。如果等于course的总数,就是我们要找的Sno

         having count(*) = (select count(*) from course ))    //统计course中共有几门课程

    另一种思路:

    引入:将题目换为 查找学号为 00003 没有选修的科目  

            思路:我们可以将已知学号代入,把每一个科目代入(循环),这将形成1*count(*)种组合。

    将这组成作为条件,一一与SC表种进行比对,找不到匹配的我们提交 。

                     select Cname from course where

                              not exists               //找不到的组合,提交course

                                   (select * from SC where course.cno = cno and sno = ''00003'')

    //在SC中匹配

    换个题目: 查找没有 没有选修科目的学生姓名

             思路:学号未知 , 科目未知,说明有两个未知变量。应该有两个EXISTS。我们可以扫描

    student 和 course共有 s * c 中组合,将这些组合与SC的每一项进行匹配,注意s*c组合已经包含所

    有可能。如果全部找到 ,就说明已经选修了全部课程。找不到就说明有课程没选修 。再将没选修的的
    提交给上一exists 循环 。若上一exists 不存在的再提交给外循环。



    最后详细回答你的问题:数据库SQL语句中 查询选修了全部课程的学生的学号和姓名 
    查询选修了全部课程的学生姓名。
            SELECT Sname
             FROM Student
             WHERE NOT EXISTS
                (SELECT *
                  FROM Course
                  WHERE NOT EXISTS
                      (SELECT *
                       FROM SC
                       WHERE Sno= Student.Sno
                          AND Cno= Course.Cno);

    理解如下:    查询选修了全部课程的学生姓名。   
    不用管怎么样,第一个select 必定是在 student 表里选 sname 既:
         SELECT Sname
             FROM Student
    加上条件即: where
    条件是什么呢? 条件就是---------------------》 查询选修了全部课程的
    因为没有    (任意一个)谓词, 只能用  EXISTS   或者  NOT EXISTS 来表示。 这点理解吧?
    所以要把条件翻译成 -----------------------》  不存在一门课程这个学生没有选修
    where后面就是  不存在(NOT EXISTS) (
            一门课程这个学生没有选修
    )

    接下来就是把Course表中的课程依次拿出来找出 没有选修的 
    怎么找呢?  因为  NOT EXISTS 子查询中 找不到的提交
    另外你要明白 ----------------------------NOT EXISTS 查询 都是相关查询----------
    所以只要把 在最后一个select 中  
                             WHERE Sno= Student.Sno
                                                 AND Cno= Course.Cno);
    就是将这个同学通过 SC 表 和  Crouse的 课程连接一遍,找到连接不上的,即: 没有选修的,  这样就找到了一门课这个学生没有选修, 存在没有选修的课,那么该学生被pass掉了,
    一次进行一个同学的判断  。



                 若你学过程序编程,可以看下面的内容, 若没有则可忽略、。----------

                上述是理解是数据库系统内部的实现,可以用for循环表示
                for(i=1; i<student.length( 学生的总人数); i++){
                                  for(i=j;j<Crouse.length(总的课门数); j++){
                                        条件就是:
                                         没有一门课没有选修                                                         
                                 }
                         }


       
    最后你找记住 
    1. 第一个select 就是 你要选的就是    学生
        SELECT Sname
             FROM Student
    2. 第二个 select 就是  课程
    3.  第三个select 就是  学生和课程发生关系的表 ------------SC选修表
       让他们连接起来



    固定的模式 1 你要的结果的表  学生
               2  满足条件的表   课程表
               3  产生关系的表   选修表
                 where    通过选修表把他们连接起来

    ============================

    查询select----存在量词查询

    exists代表存在量词ョ,该查询结果没有值,只有逻辑值真true和逻辑假false两个值。

    ex41:查询所有选修了001课程的学生名单

    select sname
    from student a
    where exists ( 
    select *
    from sc b
    where a.sno=b.sno and cno='001')

    ex42:查询没有选修了001课程的学生名单

    select sname
    from student a
    where not exists ( 
    select *
    from sc b
    where a.sno=b.sno and cno='001')

    ex43:查询选修了所有课程的学生名单。

    由于SQL中没有全称量词,可以这样理解:查询这样的学生,没有一门课程他没有选

    select sname
    from student a
    where not exists ( 
    select *
    from course b
    where not exists (
    select *
    from sc c
    where a.sno=c.sno and c.cno=b.cno))

    注意:SQL没有蕴涵谓词,可以使用等价变换进行转换

    p→q ≡ ┑p∨q

    ex43:查询至少选修了学生95002选修的全部课程的学生名单。

    将查询进行变换:

    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没有选,SQL语句如下:

    select sname,sno
    from student a
    where sno <> '95002' and not exists ( 
    select *
    from sc b
    where sno='95002' and not exists (
    select *
    from sc c
    where a.sno=c.sno and c.cno=b.cno))

  • 相关阅读:
    [转]对Lucene PhraseQuery的slop的理解
    Best jQuery Plugins of 2010
    15 jQuery Plugins To Create A User Friendly Tooltip
    Lucene:基于Java的全文检索引擎简介
    9 Powerful jQuery File Upload Plugins
    Coding Best Practices Using DateTime in the .NET Framework
    Best Image Croppers ready to use for web developers
    28 jQuery Zoom Plugins Creating Stunning Image Effect
    VS2005 + VSS2005 实现团队开发、源代码管理、版本控制(转)
    禁止状态栏显示超链
  • 原文地址:https://www.cnblogs.com/hoobey/p/7040030.html
Copyright © 2011-2022 走看看