• 学生——成绩表2.2


    一、表说明同“学生——成绩表2.1”

    二、目录

    选课情况

    1.       查询学过"张三"老师授课的同学的信息

    2.       查询没学过"张三"老师授课的同学的信息

    3.       查询选修了全部课程的学生信息

    4.       查询没有学全所有课程的同学的信息

    5.       查询出只选有两门课程的全部学生的学号和姓名

    6.       检索至少选修两门课程的学生学号

    7.       查询每门课程被选修的学生数

    8.       查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息

    9.       查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

    10.    查询学过编号为"01"并且也学过编号为"02"的但是没有学过课程"03"的同学的信息

    11.    查询至少有一门课与学号为"01"的同学所学相同的同学的信息

    12.    查询"01"号的同学学习的课程完全相同的其他同学的信息

    三、查询

    1.查询学过"张三"老师授课的同学的信息

    select distinct Student.* 
    from Student , SCore , Course , Teacher
    where Student.s_id= SCore.s_id and SCore.C_id = Course.C_id and Course.T_id = Teacher.T_id and Teacher.Tname = '张三'
    order by Student.S_id

    2.查询没学过"张三"老师授课的同学的信息

    select student.* 
    from student 
    where student.S_id not in
    (select distinct score.S_id from score , course , teacher where score.C_id = course.C_id and course.T_id = teacher.T_id and teacher.tname = N'张三')
    order by student.S_id

    分析:not in用于查询某表(或结果表)中没有的数据。

    3.查询选修了全部课程的学生信息(即参加了所有课程的考试)

    方法1

    select student.* from student where S_id in
    (select S_id from score group by S_id having count(1) = (select count(1) from course))

    分析:选修了全部课程,即参加了所有课程的考试,也就是说某位同学在score表中有三条记录(因为有三门课程),因此将score表按s_id进行分组,统计其条数,只要此条数与course表中的条数相等,即表明该组的s_id对应的同学参加了所有的考试。此SQL考察了group by与聚合函数的运用。

    注:此查询可以不用嵌套,如下SQL:

    select student.* from student
    left join score on student.s_id=score.s_id
    group by student.s_id
    having count(1) =(select count(1) from course)

    方法2 使用双重否定来完成 (注:里面一层的嵌套的where not exists 可换成 where m.s_id not in)

    select t.* from student t where t.S_id not in(
      select distinct m.S_id from
      ( select S_id , C_id from student , course) m where not exists (select 1 from score n where n.S_id = m.S_id and n.C_id = m.C_id)
    )

    分析:此SQL的查询逻辑是先查出有缺考的同学的s_id,再根据not in 查询没有缺考的(即参加了所有课程考试)同学信息,这样就可以从student表中查出指定结果了。

    现在来具体看一下是如何把有缺考的同学的s_id(m.s_id)查出来的——其实也很简单,先得到s_id与c_id的所有情况,即下面的SQL:

    select m.* from
      ( select S_id , C_id from student , course) m

    结果:

    然后与score表进行比对,利用not exists就可以查出上面结果中有的而在score表不存在的记录(上面结果中的蓝色框框中的记录)——即缺考记录,用 select distinct m.S_id 就查出了缺考记录中同学的s_id(5,6,7,8),最后再查一下student表,用not in即可查出参加了所有课程考试同学信息——即选修了所有课程的同学信息。

    方法3 使用双重否定来完成

    select t.* from student t where not exists(select 1 from(
    select distinct m.S_id from(select S_id , C_id from student , course) m where not exists (select 1 from score n where n.S_id = m.S_id and n.C_id = m.C_id)
    ) k where k.S_id = t.S_id)

    4.  查询没有学全所有课程的同学的信息

    4.1不包括什么课都没选的同学(注:可把group by 中的 Student.Sname , Student.Sage , Student.Ssex 去掉

    select Student.*
    from Student , SCore
    where Student.S_id = SCore.S_id
    group by Student.S_id , Student.Sname , Student.Sage , Student.Ssex having count(C_id) < (select count(C_id) from Course)

    4.2包括什么课都没选的同学

    select Student.*
    from Student left join SCore
    on Student.S_id = SCore.S_id
    group by Student.S_id , Student.Sname , Student.Sage , Student.Ssex having count(C_id) < (select count(C_id) from Course)

    5.查询出只选有两门课程的全部学生的学号和姓名

    select Student.S_id, Student.Sname
    from Student , SCore
    where Student.S_id = SCore.S_id
    group by Student.S_id , Student.Sname
    having count(SCore.S_id) = 2
    order by Student.S_id

    6. 检索至少选修两门课程的学生学号

    select student.S_id, student.Sname
    from student , SCore
    where student.S_id = SCore.S_id
    group by student.S_id , student.Sname
    having count(1) >= 2
    order by student.S_id

    7. 查询每门课程被选修的学生数

    7.1 只在score表中查询

    select c_id , count(S_id) 学生数 from score group by c_id

    7.2在score表、Course表中查询

    select Course.C_id , Course.Cname , count(*) 学生人数
    from Course , SCore
    where Course.C_id = SCore.C_id
    group by  Course.C_id , Course.Cname
    order by Course.C_id , Course.Cname

    7.3 统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

    select Course.C_id, Course.Cname , count(*) 学生人数
    from Course , SCore
    where Course.C_id = SCore.C_id
    group by  Course.C_id , Course.Cname
    having count(*) >= 5
    order by 学生人数 desc , Course.C_id

    8.查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息

    方法1(注:下面SQL可以将exists用in代替,'01' and exists 换成and SCore.S_id in(或and Student.S_id in),Select 1 换成Select SC_2.S_id。)

    select Student.* from Student , SCore 
    where Student.S_id = SCore.S_id and SCore.C_id= '01' and exists (
    Select 1 from SCore SC_2 where SC_2.S_id = SCore.S_id and SC_2.C_id= '02') 
    order by Student.S_id

    分析:1.该SQL的查询逻辑是首先查出符合学过编号为"01"课程这个条件的同学信息,然后对于此结果再加一条限定条件,即该结果中的s_id对应的同学也学过编号为"02"的课程,关键在于如何联结这两个条件呢?——exists。2.现在通过分析此SQL的执行过程来说明一下exists是什么意思。见下图:

    在查询的过程中,分析器会将外查询的结果的每一行代入内查询验证,为了反映内查询的结果,我们现在看下“Sql A”的执行结果(“结果A”),如分析器在分析“外查询结果”的第一行记录(赵雷那一行)时,代入内查询验证,内查询会查询score表,分析后面的where条件后,发现有这一行(“结果A”中s_id=1,c_id=2的那一行),返回true,那么分析器会将这一行作为外查询的结果行,重复此动作,一直到“外查询结果”的最后一行(吴兰那一行),分析器在分析内查询的where条件后并不能从“Sql A”中找到符合条件的记录,返回false,那么分析器就不会将该行作为外查询的结果行,所以最后的查询记录有5条。

    注意:exsits的意思并不是说将外查询的结果的每一条记录都在内查询中存在,而是以内查询与外查询的联结条件及其他条件(如果有的话)分析在内查询的表中是否存在该记录,如果存在,返回true,否则返回false,如果返回true,分析器就会将外查询的当前记录作为查询结果。

    方法2(注:下面SQL中的distinct 可去掉)

    select m.* from Student m where S_id in(
      select S_id from(
         select distinct S_id from SCore where C_id = '01'
         union all
         select distinct S_id from SCore where C_id = '02'
      ) t group by S_id having count(1) = 2
    ) order by m.S_id

    分析:此SQL的查询逻辑是先得到参加课程01考试同学的s_id和参加课程02同学是s_id,然后在此结果集中以s_id分组,统计条数等于2的s_id——即既参加课程01又参加了课程02的同学的s_id,最后查下student表,用in即可查出指定结果。需注意的是,其中必须用union all而不是union,因为需要重复的s_id以进行分组统计。

    结果:

    9.查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

    方法1

    select Student.* from Student , SCore 
    where Student.S_id = SCore.S_id and SCore.C_id = '01' and not exists (
    Select 1 from SCore SC_2 where SC_2.S_id = SCore.S_id and SC_2.C_id = '02') 
    order by Student.S_id

    方法2

    select Student.* from Student , SCore 
    where Student.S_id = SCore.S_id and SCore.C_id = '01' and Student.S_id not in (
    Select SC_2.S_id from SCore SC_2 where SC_2.S_id = SCore.S_id and SC_2.C_id = '02') 
    order by Student.S_id

    10.查询学过编号为"01"并且也学过编号为"02"的但是没有学过课程"03"的同学的信息

    select Student.* from Student , SCore 
    where Student.S_id = SCore.S_id and SCore.C_id= '01' and exists (
    Select 1 from SCore SC_2 where SC_2.S_id = SCore.S_id and SC_2.C_id= '02') and not exists(
    Select 1 from SCore SC_3 where SC_3.S_id = SCore.S_id and SC_3.C_id= '03')
    order by Student.S_id

    11.查询至少有一门课与学号为"01"的同学所学相同的同学的信息

    select distinct Student.* from Student , SCore 
    where Student.S_id = SCore.S_id and SCore.C_id in (select C_id from SCore where S_id = '01') and Student.S_id <> '01'

    分析:此SQL的查询逻辑在于先得到s_id=01同学的所有课程,再利用in进行查询。需注意的是,查询的结果需进行取重(因为有重复的结果)。

    结果:

    12.查询"01"号的同学学习的课程完全相同的其他同学的信息(注:应该此SQL运用了group by ,所以可以去掉distinct)

    select Student.* from Student where S_id in
    (select distinct SCore.S_id from SCore where S_id <> '01' and SCore.C_id in (select distinct C_id from SCore where S_id = '01')
    group by SCore.S_id having count(1) = (select count(1) from SCore where S_id='01'))

    分析:此SQL的查询逻辑在于先得到至少有一门课程与01号同学相同的信息,再查询所有课程与01号同学相同的信息。

    select distinct SCore.S_id from SCore where S_id <> '01' and SCore.C_id in (select distinct C_id from SCore where S_id = '01') 即是得到至少有一门课程与01号同学相同的信息(s_id);
    select distinct SCore.S_id from SCore where S_id <> '01' and SCore.C_id in (select distinct C_id from SCore where S_id = '01')
    group by SCore.S_id having count(1) = (select count(1) from SCore where S_id='01') 即得到所有课程均与01号同学相同的信息(s_id)——01号同学选了三门课程,在score表中有三条记录,那么与他所选课程相同的同学也应该在socre表中有三条记录。

    注意:实际上,此SQL可以直接查询所有课程与01号同学相同的信息,没有必要“先查询至少有一门课程与01号同学相同的信息,然后再以此结果查询所有课程与01号同学相同的信息”。SQL如下:
    select * from student where s_id in
    (select score.s_id from score where s_id<>1
    group by score.s_id having count(1) =(select count(1) from score where s_id=1))

  • 相关阅读:
    小程序学习资料
    tomcat单应用多实例部署报错 应用jar不存在
    nginx windows版本 1024限制
    mysql连接数
    rocketmq
    nginx路径匹配
    war包的压缩解压缩
    IIS访问HTTP Error 400. The request hostname is invalid
    Microsoft 安全扫描程序
    vscode
  • 原文地址:https://www.cnblogs.com/wql025/p/4957522.html
Copyright © 2020-2023  润新知