今天在做一个学校的学生成绩管理的时候,涉及到对学生的成绩进行排名的问题
主要的难点有两处:
1. 对不同考试项目进行分组,
2. 对同一组内的成绩并列的要做处理,
举个栗子:比如有两门考试
三年级上学期语文100,100,90,80,70,60,50,0和
三年级下学期数学100,100,99,98,98,98,97,97
正确的结果应该是
三年级上学期语文1,1,3,4,5,6,7,8
三年级下学期数学1,1,3,4,4,4,7,7
代码如下:
# 成绩排名表,所有科目,所有考试,所学学号,所有成绩
drop TABLE if exists score_rank;
CREATE TABLE score_rank
SELECT id as stuid,score,rank,score_id2 as score_id
FROM (SELECT tmp.id, tmp.score,
@incRank := IF(@Grp = score_id,@incRank + 1,1),
@curRank := IF(@Grp = score_id and @prevRank = score, @curRank, @incRank) AS rank,
@prevRank := IF(@Grp = score_id,score,100),
@Grp:=score_id as score_id2
FROM (SELECT score_stuno as id,Score_mark as score, score_id
FROM score) tmp,
(SELECT @curRank:=1, @score_id:=0,@prevRank := 100,@incRank := 0) a
order by score_id2 asc,score desc,id asc) RESULT;
附上参考链接
1.并列处理
2.分组排序
另外有时候我们还需要对成绩进行等级划分,附上代码如下
drop procedure if exists proc_get_range_num;
DELIMITER //
create procedure proc_get_range_num(in in_score_id int, in is_score_type_total int)
BEGIN
IF (is_score_type_total=1)
THEN
SELECT
sum((CASE WHEN score_mark>=295 AND score_mark <=300 THEN 1 ELSE 0 END)) A1,
sum((CASE WHEN score_mark>=290 AND score_mark < 295 THEN 1 ELSE 0 END)) A2,
sum((CASE WHEN score_mark>=285 AND score_mark < 290 THEN 1 ELSE 0 END)) B1,
sum((CASE WHEN score_mark>=280 AND score_mark < 285 THEN 1 ELSE 0 END)) B2,
sum((CASE WHEN score_mark>=270 AND score_mark < 280 THEN 1 ELSE 0 END)) C,
sum((CASE WHEN score_mark>=260 AND score_mark < 270 THEN 1 ELSE 0 END)) D,
sum((CASE WHEN score_mark>=0 AND score_mark < 260 THEN 1 ELSE 0 END)) E,
sum((CASE WHEN score_mark< 0 OR score_mark > 300 THEN 1 ELSE 0 END)) ERR
from score WHERE score_id=in_score_id;
ELSE
SELECT
sum((CASE WHEN score_mark>=95 AND score_mark <=100 THEN 1 ELSE 0 END)) A1,
sum((CASE WHEN score_mark>=90 AND score_mark < 95 THEN 1 ELSE 0 END)) A2,
sum((CASE WHEN score_mark>=85 AND score_mark < 90 THEN 1 ELSE 0 END)) B1,
sum((CASE WHEN score_mark>=80 AND score_mark < 85 THEN 1 ELSE 0 END)) B2,
sum((CASE WHEN score_mark>=70 AND score_mark < 80 THEN 1 ELSE 0 END)) C,
sum((CASE WHEN score_mark>=60 AND score_mark < 70 THEN 1 ELSE 0 END)) D,
sum((CASE WHEN score_mark>=0 AND score_mark < 60 THEN 1 ELSE 0 END)) E,
sum((CASE WHEN score_mark< 0 OR score_mark > 100 THEN 1 ELSE 0 END)) ERR
from score WHERE score_id=in_score_id;
END IF;
END //
DELIMITER ;
#0,1分别表示是总分还是单科分数
call proc_get_range_num(63, 1);call proc_get_range_num(67, 0);
统计avg max min? 还有参加考试的人数
/*****************************************************************
proc_get_num_max_min_avg_score
*****************************************************************/
drop procedure if exists proc_get_num_max_min_avg_score;
DELIMITER //
create procedure proc_get_num_max_min_avg_score(in in_score_id int)
BEGIN
SELECT
sum(case WHEN Score_mark is NULL then 0 else 1 END ) as num,
max(Score_mark) as max,
min(Score_mark) as min,
cast(avg(Score_mark) as DECIMAL(5,2)) as avg
from score WHERE score_id=in_score_id;
END //
DELIMITER ;