今天在做一個學校的學生成績管理的時候,涉及到對學生的成績進行排名的問題
主要的難點有兩處:
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 ;