美文网首页
SQL经典练习(11~14)

SQL经典练习(11~14)

作者: 蜗牛登塔尖 | 来源:发表于2019-04-10 16:47 被阅读0次
    1. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
        分析:两门及以上课程,那就是成绩表中课程数目大于等于2,不及格成绩,那就是考试成绩小于60。学生的学号,姓名信息来自students表,平均成绩是对考试成绩进行AVG函数。
    SELECT s.`S#`,s.sname,AVG(score) AS "平均成绩"
    FROM students s,SC
    WHERE  s.`S#` = SC.`S#` AND score < 60 
    GROUP BY s.`S#` ,s.sname
    HAVING COUNT(score) >= 2;
    
    查询结果
    12.检索" 01 "课程分数小于 60,按分数降序排列的学生信息
      分析:两个表联结查询,score < 60, 筛选条件课程为01,最后降序排列。
    SELECT s.*
    FROM students AS s,SC
    WHERE s.`S#` = SC.`S#` AND score < 60 AND `C#` = '01'
    ORDER BY score DESC;
    
    查询结果
    1. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
        分析:如果题目只要求“显示所有学生的平均成绩(默认升序排列)”则使用
    SELECT `S#`,AVG(score)
    FROM SC
    GROUP BY `S#`
    ORDER BY AVG(score);
    
    查询结果

      但是题目还要求显示所有课程和成绩,因此要在上面查询结果中在增加3列,分别表示课程01,02,03以及对应的成绩,如果没有成绩,成绩显示为0或者NULL等。这个让我想到了一维表转成二维表,就是原表的列是“课程”,它下面有各门课程,比如语文,数学,英语等,这种表属于典型的一维表,很多时候我们都需要这种形式的表进行表格创建,数据分析等。而如果把“课程”字段下的各门课程单独拿出来,作为新的列(字段)就变成了二维表。本题就要求进行这样的查询。“行转列”自然想到了条件判断CASE...WHEN...END,配合GROUP BY语句,对分组以后的记录,进行“遍历”筛选,符合某条件的就返回对应的值,不符合的也设定一个值,比如本题是0或者NULL。

    SELECT `S#`,MAX(CASE `C#` WHEN '01' THEN score ELSE NULL END) AS course_01,
    MAX(CASE `C#` WHEN '02' THEN score ELSE NULL END) AS course_02,
    MAX(CASE `C#` WHEN '03' THEN score ELSE NULL END) AS course_03,
    AVG(score) AS "平均成绩"
    FROM SC
    GROUP BY `S#`
    ORDER BY AVG(score) DESC;
    
    查询结果
      这段代码花费了我比较长的时间,主要是卡在了聚集函数与CASE...WHEN...END以及GROUP BY子句的联合使用。最终也是想明白了。主要是以下几点:
    (1)GROUP BY 子句后面需要分组的列名,必须是SELECT 后面的除了聚集函数以外的所有列名。如果SELECT后面包含多个列名(没有使用聚集函数SUM,AVG,MAX,MIN等),而GROUP BY后面的列名只是它们其中的一部分,系统将报错。
    (2)GROUP BY 分组,其实有点像DISTINCT,它把表的内容按照某个字段分组,该字段中,相同的数据合成为“一个”数据。之后使用聚集函数就针对每个分组进行了,不会越过某个分组跑到另外的分组。
    (3)如果使用了GROUP BY子句分组,那么SELECT 后面,需要新增的列,必须使用聚集函数,因为这样才能保证输出结果为一个。GROUP BY 分组后,查询总是只返回一个数据,聚集函数的作用就是将多个数据通过函数的方法变成一个
    (4)一定要明白SQL语句的执行顺序。
      这段代码中的MAX,其实可以更换成SUM,NULL可以更换成数字0,因为SUM函数是忽略NULL值的;三个成绩,其中两个为空(或者为0),另外一个进行SUM计算,还是本身。而它们的目的就是将多个数据通过计算变成一个数据,这样就可以返回。
    1. 查询各科成绩最高分、最低分和平均分,以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率(及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90)。 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
        分析:看到条件判断筛选的题目首先就要想到CASE...WHEN...END。“查询各科成绩”这句话提示要按照课程分组。这个题目多了一组数据,及格率等,知道及格率=及格人数/总人数,其他类似即可,这里就存在一个对60分以上的成绩进行计数计算的过程。
    SELECT c.`C#` AS "课程编号",c.`Cname` AS "课程名称",COUNT(*) AS "选修人数",
    MAX(score) AS "最高分",MIN(score) AS "最低分",AVG(score) AS "平均分",
    SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END)/COUNT(*) AS "及格率",
    SUM(CASE WHEN score > 70 AND score < 80 THEN 1 ELSE 0 END)/COUNT(*) AS "中等率",
    SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END)/COUNT(*) AS "优良率",
    SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END)/COUNT(*) AS "优秀率"
    FROM courses AS c, SC
    WHERE c.`C#` = SC.`C#`
    GROUP BY c.`C#`,c.Cname
    ORDER BY COUNT(*) DESC,c.`C#` ASC;
    
    查询结果

      这段代码,主要关注SUM与CASE的搭配使用。在GROUP BY 按照课程号和课程名称分组以后,CASE语句在每个分组内进行记录遍历,如果满足条件,值设为1,在对照第二条记录时,如果还是满足条件的,那么实现累加,即在原来1的基础上再加1,变成2,如果不满足,就是1+0=1,因为实现了对满足条件的记录计数的功能。这个类似EXCEL的COUNTIF函数。

    相关文章

      网友评论

          本文标题:SQL经典练习(11~14)

          本文链接:https://www.haomeiwen.com/subject/lbxbiqtx.html