關於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_ ) AS T1 7 WHERE 8 平均成績 > T2.平均成績 9 ) AS 名次, 10 S_ AS 學生學號, 11 平均成績 12 FROM 13 ( SELECT S_, AVG( score ) 平均成績 FROM SC GROUP BY S_ ) AS T2 14 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,方向取決於如何排序和用什麼字段進行排序。sql
B 排序算法的講解數據庫
簡單解釋下這個查詢運用到的排序算法,首先按照學生進行分組,以後運用了相關子查詢同時使用了distinct關鍵字去除了徹底相同的列。將平均成績和相同表格的平均成績進行一一比較,對於當前平均成績比其餘平均成績高的行記錄進行了計數。以表1爲例,就是學號1001的平均成績和1002-1012進行了比較,若是該成績大於其餘平均成績就+1。這時每位同窗都比較完了,那麼獲得了一個以學生編號爲分組的並且記錄了平均成績高於其餘同窗的平均成績的次數表2。此時的表2的開始值是0,所以此時1+就派上了用場,用初始值變成了1,那麼接下來對其進行排序就能夠獲得名次表,就如以上的結果演示表。函數
注:表格分解學習
表1:平均成績表spa
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:高於其餘成績次數表.net
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 +------+------+
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 Course 9 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 +--------+----------+-----------+------------+
其實這段代碼也沒有什麼能夠解釋的,就是一些函數的和選擇結構的運用code
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結尾的。