最近做了一些sql的題,想着總結一下吧,所以就有了下面這篇博文。
sql中經常會遇到一類需求:需要分段統計前N高。例如:每個班的成績前三,每科的成績前三,每個部門的工資前五等等。
這類題其實可以分成兩種情況:
1. 前1高,也就是第一。
2. 前N高,也就是前三,前五等等。
一、 前1高
第一種解決辦法
針對分段的字段(每個班的成績前三,那麼每個班就是分段字段),group by以後再根據需求max或者min就可以求出來。但是這種求出來以後,一般只有分段字段和具體的值,如果想要查學生姓名,性別等,還需要再處理(根據具體的值join或者在where中in)。
第二種解決辦法 - over()
使用over(),排序函數有三種:row_number(),rank(),dense_rank()。因爲只關心第一,所以用哪種都可以。直接用排序函數,over中對分段字段進行partition by,對具體的值進行order by,根據業務需求決定是否desc。然後嵌套子查詢,排序字段進行過濾即可。
我喜歡這種方法,因爲所有的字段都可以顯示出來,不用像group by那樣那麼麻煩。
但是mysql8.0以前好像不支持…唉
案例
光說不練假把式,不過自己寫測試案例太麻煩了,還是參考我做過的題吧: 部門工資最高的員工https://blog.csdn.net/weixin_42845682/article/details/105437193。
二、 前N高
第一種解決辦法
可以利用子查詢,可以求出,大於每個值的值有多少個。然後用N做過濾,同時配合分段字段就行。(湊合看吧)
我很不喜歡用這種辦法…感覺可讀性太差了。
第二種解決辦法 - over()
我還是喜歡這種辦法…
使用over(),排序函數有三種:row_number(),rank(),dense_rank()。根據具體的業務需求,去決定需要使用哪個。
直接用排序函數,over中對分段字段進行partition by,對具體的值進行order by,根據業務需求決定是否desc。然後嵌套子查詢,排序字段進行過濾即可。
同時,推薦想進階的同學看這個: mysql中,實現dense_rank()的效果。 - 不使用dense_rank(),實現編號排序的效果。https://blog.csdn.net/weixin_42845682/article/details/105253070
案例
光說不練假把式,不過自己寫測試案例太麻煩了,還是參考我做過的題吧: 部門工資前三高的所有員工https://blog.csdn.net/weixin_42845682/article/details/105437449。