关于mysql进行学生成绩名次和及格率的计算
前言:最近在学习mysql,然后找到了一些面试题进行了练习,发现了几个有趣的面试题,在这里特地分享给大家,有如何计算名次以及及格率
一、mysql计算成绩排名
前提:以下是样例表的结构
1 Student(S_,Sname,Sage,Ssex) 学生表2 S_:学生编号,字符串型3 Sname: 学生姓名,字符串型4 Sage:年龄 ,数值型5 Ssex:性别,字符串型6
7 Course(C_,Cname,T_) 课程表8 C_:课程编号 ,字符串型 (企业管理001,马列002,UML 003,数据库004,英语006)9 Cname:课程名称 ,字符串型10 T_:教师编号,字符串型11
12 SC(S_,C_,score) 成绩表13 S_:学生编号 ,字符串型14 C_:课程编号 ,字符串型15 score:成绩,数值型16
17 Teacher(T_,Tname) 教师表18 T_:教师编号 ,字符串型19 Tname:教师姓名,字符串型
(一) 代码演示
1 SELECT
2 1+(3 SELECT
4 COUNT( DISTINCT平均成绩 )5 FROM
6 ( SELECT S_, AVG( score ) AS 平均成绩 FROM SC GROUP BY S_ ) AST17 WHERE
8 平均成绩 >T2.平均成绩9 ) AS名次,10 S_ AS学生学号,11 平均成绩12 FROM
13 ( SELECT S_, AVG( score ) 平均成绩 FROM SC GROUP BY S_ ) AST214 ORDER BY
15 平均成绩 DESC;
(二) 结果演示
1 +------+----------+-----------+
2 | 名次 | 学生学号 | 平均成绩 |
3 +------+----------+-----------+
4 | 1 | 1005 | 99.000000 |
5 | 2 | 1010 | 85.500000 |
6 | 3 | 1003 | 84.250000 |
7 | 4 | 1004 | 75.000000 |
8 | 5 | 1007 | 71.333333 |
9 | 6 | 1006 | 68.250000 |
10 | 7 | 1012 | 66.000000 |
11 | 8 | 1011 | 57.750000 |
12 | 9 | 1001 | 56.000000 |
13 | 10 | 1002 | 47.500000 |
14 | 11 | 1008 | 44.000000 |
15 | 12 | 1009 | 34.000000 |
16 +------+----------+-----------+
17 12 rows in set (0.06 sec)
(三) 内容讲解
上述的查询语句中运用了很多技巧,但是我们只挑几个重点进行讲解,至于相关自查询就没有讲解,以及distinct也没有讲解,distinct的讲解这里推荐一篇博文。
A n+的使用
n+放在()子查询的前面,这里的n是表明指定的字段的数值是从n开始的,如果是1就是从1开始,2就是从2开始。然后+的意思就是该字段的值从n开始每次都+1,这里和Java自增++的使用有些神似,当然这是这两个完全没有关系。这里是1+那么就是从1开始每个值加1,方向取决于如何排序和用什么字段进行排序。
B 排序算法的讲解
简单解释下这个查询运用到的排序算法,首先按照学生进行分组,之后运用了相关子查询同时使用了distinct关键字去除了完全相同的列。将平均成绩和相同表格的平均成绩进行一一比较,对于当前平均成绩比其他平均成绩高的行记录进行了计数。以表1为例,就是学号1001的平均成绩和1002-1012进行了比较,如果该成绩大于其他平均成绩就+1。这时每位同学都比较完了,那么得到了一个以学生编号为分组的而且记录了平均成绩高于其他同学的平均成绩的次数表2。此时的表2的开始值是0,因此此时1+就派上了用场,用初始值变成了1,那么接下来对其进行排序就可以得到名次表,就如以上的结果演示表。
注:表格分解
表1:平均成绩表
1 +------+-----------+
2 | S_ | 平均成绩 |
3 +------+-----------+
4 | 1001 | 56.000000 |
5 | 1002 | 47.500000 |
6 | 1003 | 84.250000 |
7 | 1004 | 75.000000 |
8 | 1005 | 99.000000 |
9 | 1006 | 68.250000 |
10 | 1007 | 71.333333 |
11 | 1008 | 44.000000 |
12 | 1009 | 34.000000 |
13 | 1010 | 85.500000 |
14 | 1011 | 57.750000 |
15 | 1012 | 66.000000 |
16 +------+-----------+
表2:高于其他成绩次数表
1 +------+------+
2 | 学号 | 次数 |
3 +------+------+
4 | 1001 | 8 |
5 | 1002 | 9 |
6 | 1003 | 2 |
7 | 1004 | 3 |
8 | 1005 | 0 |
9 | 1006 | 5 |
10 | 1007 | 4 |
11 | 1008 | 10 |
12 | 1009 | 11 |
13 | 1010 | 1 |
14 | 1011 | 7 |
15 | 1012 | 6 |
16 +------+------+
二、mysql计算及格率
(一) 代码演示
1 SELECT
2 t.C_ AS课程号,3 max( course.Cname ) AS课程名,4 ifnull( AVG( score ), 0 ) AS平均成绩,5 100 * SUM( CASE WHEN ifnull( score, 0 ) >= 60 THEN 1 ELSE 0 END ) / COUNT( * ) AS及格百分数6 FROM
7 SC T,8 Course9 WHERE
10 t.C_ =course.C_11 GROUP BY
12 t.C_13 ORDER BY
14 ifnull(avg(score),0),100 * SUM( CASE WHEN ifnull( score, 0 ) >= 60 THEN 1 ELSE 0 END ) / COUNT( * ) DESC;
(二) 结果演示
1 +--------+----------+-----------+------------+
2 | 课程号 | 课程名 | 平均成绩 | 及格百分数 |
3 +--------+----------+-----------+------------+
4 | 004 | 数据库 | 48.200000 | 40.0000 |
5 | 001 | 企业管理 | 59.142857 | 57.1429 |
6 | 002 | 马列 | 65.400000 | 60.0000 |
7 | 006 | 英语 | 67.750000 | 75.0000 |
8 | 003 | UML | 84.750000 | 100.0000 |
9 +--------+----------+-----------+------------+
(三) 内容讲解
其实这段代码也没有什么可以解释的,就是一些函数的和选择结构的运用
A ifnull()函数的使用
这里的ifnull的作用是为了保证成绩不为空,其实就是将为空的成绩变成0,方便计算。ifnull函数的用法是ifnull(字段,值(如果前面的字段值是null就返回此值)),推荐一个博客讲述该函数用法。其实ifnull也可以用coalesce()函数进行替代,他们的用法是完全一样的,或者使用if(表达式1,值1,值2)。
B case嵌套在聚集函数sum()
这里确实是一个新的知识点,一般我们很少在聚集函数中去嵌套选择结构或者语法,这里却用到了这样的方法让人耳目一新。这里的case语句的作用是使得大于60的成绩为1和小于60为0,为了方便sum函数统计及格人数。值得注意的一点是这里case的用法和平时的语法不一样,一般在非自定义函数或者存储过程中的case用法是(case 字段 when 条件 then 值 else 值 end 字段)。但是这里直接就case 然后中间一样之后就end了。这一点是非常需要注意的,当然在存储过程中又不一样,存储过程中的case是以end case结尾的。