sql查询成绩最高分_sql查询各科成绩前三名----详述过程,思路清晰不烧脑!
一、建表造數據
建表:
create table scores( name varchar(100), subject varchar(100), score int );插入數據:
insert into scores values ('學生a','java','100'), ('學生b','java','90'), ('學生c','java','90'), ('學生d','java','60'), ('學生e','java','80'), ('學生a','python','100'), ('學生b','python','90'), ('學生c','python','90'), ('學生d','python','60'), ('學生e','python','80');二、使用myql查詢
2.1 不考慮并列情況
方法一:使用加行號的方式查詢
加行號的使用規則是:@rowNum:=num意思是聲明一個叫 rowNum 的變量并賦值為num示例: 現在有一個需求是: “查詢學生 java 課的成績、姓名并排名?”
select score,name,@m1:=@m1+1 r from scores,(select @m1:=0)a where subject='java' order by score desc 1查詢結果如下
此處加行號m1的作用就可以體現出來,查詢語句中多了一個字段 r ,他可以以數字1,2,3,4,5的形式顯示排名
由此引申,此條查詢語句結尾在加上 limit 3 便可以取出前三名
select score,name,@m1:=@m1+1 r from scores,(select @m1:=0)a where subject='java' order by score desc limit 3再引申,若要查詢所有課程的成績,取前三名,則就需要將其他的課程表 join 在一起,關聯條件為每條查詢語句的行號相等
select s1.score "java成績",s1.name,s2.score "python成績",s2.name,s1.r "排名" from (select score,name,@m1:=@m1+1 r from scores,(select @m1:=0)a where subject='java' order by score desc limit 3)s1 join (select score,name,@m2:=@m2+1 r from scores,(select @m2:=0)b where subject='python' order by score desc limit 3)s2 on s1.r=s2.r;輸出結果為:
這種方法查詢實際上是 列轉行 的方式,將字段subject 列 轉成 行 輸出。優點 是容易理解,增加了一個字段顯示排名,更加直觀。缺點 是在關聯條件多(比如課程數量大于10,查詢每科前10名,前20名成績…)的情況下, join 關聯10次以上,頻繁的join會損耗系統很多性能,嚴重的會直接堵塞死。且有個弊端是寫查詢語句的時候必須要知道具體有幾門課及課程名稱,where 條件就已經限定了每門課的課程id或者課程名稱,但有些情況下表數據量很大的時候,這種方法是不合適的。
方法二:使用子查詢嵌套查詢(使用最多)
select s1.* from scores s1 where (select count(1) from scores s2 where s1.subject=s2.subject and s1.score<s2.score)<3 order by s1.subject,s1.score desc;查詢結果如下:
這種方法比較難懂,但是查詢速度快且代碼簡單,解析如下:首先如果要查詢所有課程的成績,如下:
再對各科成績倒序排列輸出:
然后 取各科成績前三名,就需要嵌套子查詢進行篩選,代碼如下:
select s1.* from scores s1 where (select count(1) from scores s2 where s1.subject=s2.subject and s1.score<s2.score)<3 order by s1.subject,s1.score desc;查詢語句重點在于 -->子查詢語句: select count(1) from scores s2 where s1.subject=s2.subject and s1.score<s2.score意思是:統計學生個數,即關聯兩個分數表s1、s2,外層查詢每查詢一次,再到內層循環中查詢表s2,當課程名相同時,統計 s1.score<s2.score 即表s2中成績大于s1的人數有幾人。這么說可能還是有點懵,現在我們來走一遍流程,從頭到尾依次遍歷一次,詳細說明:
首先從學生a開始查詢:
→學生b:
→學生c:
→學生d:
→學生e:
此時從學生a到e的 “java” 課程前三名已經篩選完成,對于 “python” 課程,重復上述流程即可全部篩選完畢最后再對查詢出的課程、分數倒序排列即可 :order by s1.subject,s1.score desc
2.2 考慮并列情況
select s1.name,s1.subject,s1.score from scores s1 left join (select distinct subject,score from scores) s2 on s1.subject=s2.subject and s1.score<s2.score group by s1.name,s1.subject,s1.score having count(1)<3 order by subject,score desc;查詢結果如下:
很直觀的可以看出,學生b和c成績都為90分,并列第二名,學生e成績80分,為第三名
查詢語句解析:這是在 2.1方法二 的基礎上,使用 distinct 關鍵字對表s2中存在多名同學分數相同的情況進行 去重,從而達到并列排名的目的。需要注意的是,由于groub by 的條件是表s1中的字段,所以 count(1) 統計的是表s1中每次查詢s1.score<s2.score 成績低于表s2的學生人數,滿足條件小于3,就可以取出前三名
三、使用hive查詢前三名
使用hive查詢需要調用 窗口函數,類似于 2.1方法一 中加行號查詢,但使用不同的窗口函數可以實現并列與不并列的排名順序
3.1 不考慮并列情況:rank()
select * from (select name,subject,score,rank() over (partition by subject order by score desc) ranks from scores)s where ranks<4;查詢結果如下:
3.2 考慮并列情況:dense_rank()
select * from (select name,subject,score,dense_rank() over (partition by subject order by score desc) ranks from scores)s where ranks<4;查詢結果如下:
是不是非常簡單!
總結
以上是生活随笔為你收集整理的sql查询成绩最高分_sql查询各科成绩前三名----详述过程,思路清晰不烧脑!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python优雅代码大全_代码这样写更优
- 下一篇: 合并多个word的代码_快速合并多个wo