SQL经典练习题+解析 「100%可以运行」

在这里插入图片描述

一、创建答题环境

二、经典题目

  1. 查询至少参加 01 和 02 两门课程考试的相关信息(查出 Sid 相关成绩 即可)

    -- 按照上面的描述我们只需要查 SC 这张表即可,查询出两门成绩即可
    select sc1.SId, sc1.score, sc2.score
    from (select * from sc where cid = '01') sc1
         inner join
     (select * from sc where cid = '02') sc2
    on sc1.sid = sc2.sid;
    
    SIdscorescore
    0180.090.0
    0270.060.0
    0380.080.0
    0450.030.0
    0576.087.0

    扩展:查询参加 01 02 03 三门课程的考试成绩和学生 id

    select sc1.SId, sc1.score as score1, sc2.score as score2, sc3.score as score2
    from (select * from sc where cid = '01') sc1
         join
     (select * from sc where cid = '02') sc2
         join
     (select * from sc where cid = '03') sc3
    on sc1.sid = sc2.sid and sc2.SId = sc3.SId;
    
    SIdscore1score2score2
    0180.090.099.0
    0270.060.080.0
    0380.080.080.0
    0450.030.020.0
  2. 查询参加 01 课程但是可能没有参加 02 课程的情况(不存在时显示null)

    -- 典型的连接查询,使用左连接即可
    select sc1.SId, sc1.score, sc2.score
    from (select * from sc where cid = '01') sc1
         left join
     (select * from sc where cid = '02') sc2
    on sc1.sid = sc2.sid;
    
    SIdscorescore
    0180.090.0
    0270.060.0
    0380.080.0
    0450.030.0
    0576.087.0
    0631.0NULL
  3. 查询可能没有参加 01 课程但是肯定参加 02 课程的情况(不存在时显示null)

    -- 使用右连接查询即可
    select sc2.SId, sc1.score, sc2.score
    from (select * from sc where cid = '01') sc1
     right join
     (select * from sc where cid = '02') sc2
    on sc1.sid = sc2.sid;
    
    SIdscorescore
    0180.090.0
    0270.060.0
    0380.080.0
    0450.030.0
    0576.087.0
    07NULL89.0
  4. 查询编号为的 01 课程比编号为 02 课程分数高的学生信息和课程分数

    -- 思路:首先要查出 01 和 02 课程的信息,然后使用学生 id 连接起来
    -- 这样就得到课程 01 比较 02 分数高的学生的 id 和相关的成绩
    select sc1.SId, sc1.score as sorce1, sc2.score as sorce2
    from (select SId, CId, score from SC where CId = '01') as sc1
         inner join
         (select SId, CId, score from SC where CId = '02') as sc2
         on sc1.SId = sc2.SId
    where sc1.score > sc2.score;
    
    SIdsorce1sorce2
    270.060.0
    450.030.0

    将上一步查询出的结果做子集使用 sid 与 student 表进行连接然后提取出相关信息即可

    在这里插入图片描述

    IdSnameSageSsexsorce1sorce2
    2钱电1990-12-21 00:00:0070.060.0
    4李云1990-12-06 00:00:0050.030.0
  5. 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩

    -- 连接以后使用 group by 分组即可
    select Sc.SId, s.Sname, avg(score) avg_s
    from SC
    inner join Student S
    on SC.SId = S.SId
    group by S.Sname, Sc.SId
    having avg_s > 60;
    
    IdSnameavg_s
    5周梅81.50000
    3孙风80.00000
    1赵雷89.66667
    7郑竹93.50000
    2钱电70.00000
  6. 查询在 SC 表存在成绩的学生信息

    -- 两边连接一起后使用 distinct 学生信息去重
    select distinct student.*
    from student
    join SC S
    on Student.SId = S.SId;
    
    SIdSnameSageSsex
    01赵雷1990-01-01 00:00:00
    02钱电1990-12-21 00:00:00
    03孙风1990-12-20 00:00:00
    04李云1990-12-06 00:00:00
    05周梅1991-12-01 00:00:00
    06吴兰1992-01-01 00:00:00
    07郑竹1989-01-01 00:00:00
  7. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的成绩总和

    select Sname, count(SC.CId), sum(score)
    from SC
         join Student S on SC.SId = S.SId
    group by SC.SId, S.Sname;
    
    Snamecount(SC.CId)sum(score)
    赵雷3269.0
    钱电3210.0
    孙风3240.0
    李云3100.0
    周梅2163.0
    吴兰265.0
    郑竹2187.0
  8. 查询 李 姓老师的数量

    select count(1)
    from Teacher
    where Tname like '李%';
    
    count(1)
    1
  9. 查询 张三 老师授课的同学信息
    首先查出张三老师授课的信息 Cid Cname

    select CId, Cname
    from Course
         join Teacher T on Course.TId = T.TId
    where Tname = '张三';
    
    IdCname
    2数学

    再通过 SC 表查出学生信息

    select SId, Cname
    from SC join
    (select CId, Cname from Course
    join Teacher T
    on Course.TId = T.TId
    where Tname = '张三') as CS
    on CS.CId = SC.CId;
    
    IdCname
    1数学
    2数学
    3数学
    4数学
    5数学
    7数学

    最后再通过 Student 查询相关的学生信息即可

    select *
    from Student
    where SId in (
    select SId
    from SC
    join (select CId, Cname
    from Course
    join Teacher T on Course.TId = T.TId
    where Tname = '张三') as cs
    on SC.CId = cs.CId);
    
    IdSnameSageSsex
    1赵雷1990-01-01 00:00:00
    2钱电1990-12-21 00:00:00
    3孙风1990-12-20 00:00:00
    4李云1990-12-06 00:00:00
    5周梅1991-12-01 00:00:00
    7郑竹1989-01-01 00:00:00

    解法二:inner join 将三张表连接起来然后查询

    在这里插入图片描述

  10. 查询没有参与所有考试的学生的信息
    首先从 SC 表中查询出每名同学参考考试的总数

    select SId, count(CId) from SC group by SC.SId;
    
    Idcount(CId)
    13
    23
    33
    43
    52
    62
    72

    组合一下查询出参与了所有考试的学生的 Sid

    select SId from SC group by SC.SId
    having count(CId) = (select count(1) from Course);
    
    SId
    1
    2
    3
    4

    查询出的全是参加过所有考试的学生 Sid 现在只需要结合 Student 表 not in 即可

    SELECT Student.*
    FROM Student
    WHERE SId NOT IN
      (SELECT SId
       FROM SC
       GROUP BY SC.SId
    having count(CId) = (select count(1) from Course));
    
    IdSnameSageSsex
    5周梅1991-12-01 00:00:00
    6吴兰1992-01-01 00:00:00
    7郑竹1989-01-01 00:00:00
    9张三2017-12-20 00:00:00
    0李四2017-12-25 00:00:00
    1李四2012-06-06 00:00:00
    2赵六2013-06-13 00:00:00
    3孙七2014-06-01 00:00:00
  11. 查询至少一门参加的考试课程与学号为 01 的同学所参加的考试课程相同的同学信息
    这道题相对比较简单,首先查出 01 号同学参与的所有课程的 Cid

    select CId from SC where SId = 01;
    
    CId
    1
    2
    3

    接下来从 SC 表中查出参与考试与 01 号至少有一门相同的 Sid 使用 distinct 去重再使用 Student 表查出学生详细信息

    select * from Student where SId in (
    select distinct SId from SC
    where CId in (
    select CId from SC
    where SId = 01));
    
    IdSnameSageSsex
    1赵雷1990-01-01 00:00:00
    2钱电1990-12-21 00:00:00
    3孙风1990-12-20 00:00:00
    4李云1990-12-06 00:00:00
    5周梅1991-12-01 00:00:00
    6吴兰1992-01-01 00:00:00
    7郑竹1989-01-01 00:00:00
  12. 查询与 “01” 号的同学参加的考试课程完全相同的其他同学的信息
    首先从课程数量上过滤一部分学生,比如 01 参加 5 门考试,找一样的话优先考虑也参加 5 门的否则何谈相同

    SELECT Student.*
    FROM Student
    WHERE sid IN
      (SELECT sid
       FROM sc
       GROUP BY sid
       HAVING COUNT(sid) =
    (SELECT COUNT(cid) FROM sc WHERE sid = '01'));
    
    IdSnameSageSsex
    1赵雷1990-01-01 00:00:00
    2钱电1990-12-21 00:00:00
    3孙风1990-12-20 00:00:00
    4李云1990-12-06 00:00:00
    SELECT Student.*
    FROM Student
    WHERE sid IN
      (SELECT sid
       FROM sc
       GROUP BY sid
       HAVING COUNT(sid) =
              (SELECT COUNT(cid) FROM sc WHERE sid = '01')
      )
      AND sid NOT IN
      (SELECT sid
       FROM sc
       WHERE cid IN
       (SELECT DISTINCT cid FROM sc WHERE cid NOT IN
            (SELECT cid FROM sc WHERE sid = '01'))
       GROUP BY sid
      )
     AND sid NOT IN ('01');
    
  13. 查询没有参加 “张三” 老师讲授的任一门课程考试的学生的名字
    首先需要查询出张三老师授课 Cid 使用 Course 和 Teacher 表

    select cid
    from Teacher
    join Course C on Teacher.TId = C.TId
    where Tname = '张三';
    select *
    
    # from SC
    # left join (
    # select cid
    # from Teacher
    # join Course C on Teacher.TId = C.TId
    # where Tname = '张三') as SR
    # on SC.CId = SR.CId
    # where SR.cid is not null;;
    
    cid
    2

    将 SC 表和张三老师讲授表进行 左 连接

    select *
    from SC
    left join (
    select cid
    from Teacher
    join Course C on Teacher.TId = C.TId
    where Tname = '张三') as SR
    on SC.CId = SR.CId;
    
    SIdCIdscorecid
    10290.002
    20260.002
    30280.002
    40230.002
    50287.002
    70289.002
    10180.0NULL
    10399.0NULL
    20170.0NULL
    20380.0NULL
    30180.0NULL
    30380.0NULL
    40150.0NULL
    40320.0NULL
    50176.0NULL
    60131.0NULL
    60334.0NULL
    70398.0NULL

    我们可以看到没有参加张三老师课程的位置都为 NULL 直接使用 join 即可

    select *
    from SC
    join (
    select cid
    from Teacher
    join Course C on Teacher.TId = C.TId
    where Tname = '张三') as SR
    on SC.CId = SR.CId;
    
    SIdCIdscorecid
    10290.002
    20260.002
    30280.002
    40230.002
    50287.002
    70289.002

    目前 Sid 就已经参加 张三老师课程 的学生 Sid 目前只需要从 Student 中 not in 即可

    select * from Student 
    where SId not in (
    select SId
    from SC
    join (
    select cid
    from Teacher
    join Course C on Teacher.TId = C.TId
    where Tname = '张三') as SR
    on SC.CId = SR.CId);
    
    IdSnameSageSsex
    6吴兰1992-01-01 00:00:00
    9张三2017-12-20 00:00:00
    0李四2017-12-25 00:00:00
    1李四2012-06-06 00:00:00
    2赵六2013-06-13 00:00:00
    3孙七2014-06-01 00:00:00
  14. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
    首先从 SC 表中查出 60 分以下并且大于等于 2 学生信息 使用分组即可

    select SId, count(*) as num, avg(score) as avg_num
    from SC
    where score < 60
    group by Sc.SId
    having num >= 2;
    
    SIdnumavg_num
    4333.33333
    6232.50000

    现在 Sid 和平均分已经有了,只需要和学生表进行连接即可

    select Si.Sid, Sname, avg_num
    from Student
         join
    (select SId, count(*) as num, avg(score) as avg_num
    from SC
    where score < 60
    group by Sc.SId
    having count(1) >= 2) as Si
    on Si.SId = Student.SId;
    
    idSnameavg_num
    4李云33.33333
    6吴兰32.50000
  15. 检索" 01 "课程分数小于 60,按分数降序排列的学生信息
    这道题相对容易 SC 查询到相关信息然后连接 Student 即可

    select Student.*, score from Student
    join (select SId, score
    from SC
    where CId = '01' and score < 60) as Si
    on Student.SId = Si.SId
    order by score desc;
    
  16. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
    先查询出平均分然后与 SC 表进行连接即可

    select SC.SId, score, avg_num.avg_score from SC join
    (select sid, avg(score) as avg_score from sc group by sid) avg_num
    on SC.SId = avg_num.SId
    order by avg_score desc ;
    
    Idscoreavg_score
    789.093.50000
    798.093.50000
    180.089.66667
    190.089.66667
    199.089.66667
    576.081.50000
    587.081.50000
    380.080.00000
    380.080.00000
    380.080.00000
    260.070.00000
    280.070.00000
    270.070.00000
    450.033.33333
    430.033.33333
    420.033.33333
    631.032.50000
    634.032.50000
  17. 查询各科成绩最高分、最低分和平均分
    直接按照 Cid 进行分组即可然后连接 Course 即可

    select Course.Cname, max_score, min_score, avg_score
    from Course
         join
     (select CId, max(score) max_score, min(score) min_score, avg(score) 			avg_score
      from SC
      group by CId) as Si
     on Si.CId = Course.CId;
    
    Cnamemax_scoremin_scoreavg_score
    语文80.031.064.50000
    数学90.030.072.66667
    英语99.020.068.50000

    扩展:继上题目 课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 (及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90)
    在这里插入图片描述

    namemax_scoremin_scoreavg_scorep_pated_ratehd_rate
    80.031.064.500000.66670.50000.0000
    90.030.072.666670.66670.50000.1667
    99.020.068.500000.66670.33330.3333
  18. 查询出只参加两门课程考试的学生学号和姓名
    通过 SC 表查出参与两门课程的同学信息然后连接 Student 表即可

    select S.SId, S.Sname from Student as S
    join (select SId, count(SC.CId) as num
    from SC
    group by SC.SId) as Si on S.SId = Si.SId
    where num = 2;
    
    idsname
    5周梅
    6吴兰
    7郑竹
  19. 查询男生、女生人数

    select Ssex, count(1)
    from Student
    group by Student.Ssex;
    
    sexcount(1)
    8
    4
  20. 查询名字中含有 风 字的学生信息

    select * from student where sname like '%风%';
    
    IdSnameSageSsex
    3孙风1990-12-20 00:00:00
  21. 查询同名同姓学生名单,并统计人数

    select Sname,count(*) as num
    from Student
    group by Student.Sname
    having num > 1;
    
    Snamenum
    李四2
  22. 查询1990年出生的学生名单

    select * from Student where date_format(Sage, '%Y') = 1990;
    
    IdSnameSageSsex
    1赵雷1990-01-01 00:00:00
    2钱电1990-12-21 00:00:00
    3孙风1990-12-20 00:00:00
    4李云1990-12-06 00:00:00
  23. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号排序

    select cid, avg(score) as avgScore from sc
    group by cid order by avgScore desc, cid asc ;
    
  24. 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩

    select Si.SId, Student.Sname, Si.avg_score from Student
    join
    (select sid, avg(score) as avg_score from SC
    group by SC.SId
    having avg_score > 85) as Si on Student.SId = Si.SId;
    
    IdSnameavg_score
    1赵雷89.66667
    7郑竹93.50000
  25. 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数

    select S2.SId, S2.Sname, Course.Cname, S.score
    from Course
         join SC S on Course.CId = S.CId
         join Student S2 on S.SId = S2.SId
    where Course.Cname = '数学' and score < 60;
    
    IdSnameCnamescore
    4李云数学30.0
  26. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)

    select Student.SId, Student.Sname, Course.Cname, S.score
    from Student
    left join SC S on Student.SId = S.SId
    left join Course on S.CId = Course.CId;
    
    IdSnameCnamescore
    1赵雷语文80.0
    2钱电语文70.0
    3孙风语文80.0
    4李云语文50.0
    5周梅语文76.0
    6吴兰语文31.0
    1赵雷数学90.0
    2钱电数学60.0
    3孙风数学80.0
    4李云数学30.0
    5周梅数学87.0
    7郑竹数学89.0
    1赵雷英语99.0
    2钱电英语80.0
    3孙风英语80.0
    4李云英语20.0
    6吴兰英语34.0
    7郑竹英语98.0
    9张三NULLNULL
    0李四NULLNULL
    1李四NULLNULL
    2赵六NULLNULL
    3孙七NULLNULL
  27. 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数

    select S2.SId, S2.Sname, C.Cname, S.score
    from Course C
         join SC S on C.CId = S.CId
         join Student S2 on S.SId = S2.SId
    where S.score > 70;
    
    IdSnameCnamescore
    1赵雷语文80.0
    1赵雷数学90.0
    1赵雷英语99.0
    2钱电英语80.0
    3孙风语文80.0
    3孙风数学80.0
    3孙风英语80.0
    5周梅语文76.0
    5周梅数学87.0
    7郑竹数学89.0
    7郑竹英语98.0
  28. 查询每门课程不及格的人数

    select Course.CId, Course.Cname, TempC.sn from Course join
    (select Cid, count(*) as sn from SC where score < 60 group by CId) as TempC
    on TempC.CId = Course.CId;
    
    IdCnamesn
    1语文2
    2数学1
    3英语2
  29. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名

    select S.SId, S.Sname, SC.score
    from SC	
    join Student S on SC.SId = S.SId
    where SC.CId = 01
    and SC.score >= 80;
    
    IdSnamescore
    1赵雷80.0
    3孙风80.0
  30. 成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
    不想使用子查询就直接将三张表连接在一起即可

    select Student.*, S.score, T.Tname
    from Student
         join SC S on Student.SId = S.SId
         join Course C on S.CId = C.CId
         join Teacher T on C.TId = T.TId
    where T.Tname = '张三'
    order by S.score desc
    limit 1;
    
    IdSnameSageSsexscoreTname
    1赵雷1990-01-01 00:00:0090.0张三
  31. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

    select distinct a.*
    from sc a
         inner join sc b on a.score = b.score
    where a.CId != b.CId;
    
    IdCIdscore
    20380.0
    30280.0
    30380.0
    10180.0
    30180.0
  32. 统计每门课程的学生选修人数(超过 5 人的课程才统计)

    select Cname, count(*) as num
    from SC
         join Course C on SC.CId = C.CId
    group by C.Cname
    having num > 5;
    
    namenum
    6
    6
    6
  33. 统计每门课程的学生选修人数(超过 5 人的课程才统计)

    select S.Sname, count(SC.CId) as num
    from SC
         join Student S on SC.SId = S.SId
    group by S.Sname
    having num >= 2;
    
    namenum
    吴兰2
    周梅2
    孙风3
    李云3
    赵雷3
    郑竹2
    钱电3
  34. 查询选修了全部课程的学生信息

    select Sname, count(CId) selection_num
    from SC
         join Student S on SC.SId = S.SId
    group by S.Sname
    having selection_num = (select count(1) from Course);
    
    nameselection_num
    孙风3
    李云3
    赵雷3
    钱电3
  35. 查询各学生的年龄,只按年份来算

    -- 两种方法都可以
    select sname, timestampdiff(year, sage, now()) as sage from student;
    select sname, year(now()) - year(sage) as sage from student;
    
    namesage
    赵雷30
    钱电30
    孙风30
    李云30
    周梅29
    吴兰28
    郑竹31
    张三3
    李四3
    李四8
    赵六7
    孙七6
  36. 查询本周过生日的学生

    select sname from student where week(Sage) = week(now());
    
    name
    孙七
SQL是高级的非过程化编程语言,是沟通数据库服务器和客户端的重要工具,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以,具有完全不同底层结构的不同数据库系统,可以使用相同的SQL语言作为数据输入与管理的SQL接口。 它以记录集合作为操作对象,所有SQL语句接受集合作为输入,返回集合作为输出,这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入,所以SQL语句可以嵌套,这使它具有极大的灵活性和强大的功能,在多数情况下,在其他语言中需要一大段程序实现的功能只需要一个SQL语句就可以达到目的,这也意味着用SQL语言可以写出非常复杂的语句。    结构化查询语言(Structured Query Language)最早是IBM的圣约瑟研究实验室为其关系数据库管理系统SYSTEM R开发的一种查询语言,它的前身是SQUARE语言。SQL语言结构简洁,功能强大,简单易学,所以自从IBM公司1981年推出以来,SQL语言得到了广泛的应用。如今无论是像Oracle、Sybase、DB2、Informix、SQL Server这些大型的数据库管理系统,还是像Visual Foxpro、PowerBuilder这些PC上常用的数据库开发系统,都支持SQL语言作为查询语言。    美国国家标准局(ANSI)与国际标准化组织(ISO)已经制定了SQL标准。ANSI是一个美国工业和商业集团组织,负责开发美国的商务和通讯标准。ANSI同时也是ISO和International Electrotechnical Commission(IEC)的成员之一。ANSI 发布与国际标准组织相应的美国标准。1992年,ISO和IEC发布了SQL国际标准,称为SQL-92。ANSI随之发布的相应标准是ANSI SQL-92。ANSI SQL-92有时被称为ANSI SQL。尽管不同的关系数据库使用的SQL版本有一些差异,但大多数都遵循 ANSI SQL 标准。SQL Server使用ANSI SQL-92的扩展集,称为T-SQL,其遵循ANSI制定的 SQL-92标准。    SQL语言包含4个部分:    数据定义语言(DDL),例如:CREATE、DROP、ALTER等语句。    数据操作语言(DML),例如:INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。    数据查询语言(DQL),例如:SELECT语句。    数据控制语言(DCL),例如:GRANT、REVOKE、COMMIT、ROLLBACK等语句。    SQL语言包括三种主要程序设计语言类别的语句:数据定义语言(DDL),数据操作语言(DML)及数据控制语言(DCL)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值