在某些應用場景中,我們經常會遇到一些排名的問題,比如按成績或年齡排名。排名也有多種排名方式,如直接排名、分組排名,排名有間隔或排名無間隔等等,這篇文章將總結幾種mysql中常見的排名問題。
create
table scores_tb (
id int
auto_increment
primary
key,
xuehao int
notnull
, score int
notnull
)engine
=innodb
default
charset
=utf8;
insert
into scores_tb (xuehao,score)
values
(1001,89
),(1002,99
),(1003,96
),(1004,96
),(1005,92
),(1006,90
),(1007,90
),(1008,94
);# 檢視下插入的資料
mysql>
select
*from scores_tb;
+----+--------+-------+
| id | xuehao | score |
+----+--------+-------+|1
|1001|89
||2|
1002|99
||3|
1003|96
||4|
1004|96
||5|
1005|92
||6|
1006|90
||7|
1007|90
||8|
1008|94
|+----+--------+-------+
按分數高低直接排名,從1開始,往下排,類似於row number。下面我們給出查詢語句及排名結果。
# 查詢語句
select xuehao, score,
@currank :=
@currank+1
as rank
from scores_tb,
(select
@currank :=
0) r
order
by score desc
;# 排序結果
+--------+-------+------+
| xuehao | score | rank |
+--------+-------+------+
|1002|99
|1||
1003|96
|2||
1004|96
|3||
1008|94
|4||
1005|92
|5||
1006|90
|6||
1007|90
|7||
1001|89
|8|+
--------+-------+------+
# 查詢語句
select xuehao, score,
case
when
@prevrank
= score then
@currank
when
@prevrank := score then
@currank :=
@currank+1
endas rank
from scores_tb,
(select
@currank :=0,
@prevrank :=
null
) rorder
by score desc
;# 排名結果
+--------+-------+------+
| xuehao | score | rank |
+--------+-------+------+
|1002|99
|1||
1003|96
|2||
1004|96
|2||
1008|94
|3||
1005|92
|4||
1006|90
|5||
1007|90
|5||
1001|89
|6|+
--------+-------+------+
另外一種排名方式是相同的值排名相同,相同值的下乙個名次應該是跳躍整數值,即排名有間隔。
# 查詢語句
select xuehao, score, rank from
(select xuehao, score,
@currank :=if(
@prevrank
= score,
@currank
,@incrank
)as rank,
@incrank :=
@incrank+1
,@prevrank := score
from scores_tb,
(select
@currank :=0,
@prevrank :=
null
,@incrank :=
1) r
order
by score desc
) s;
# 排名結果
+--------+-------+------+
| xuehao | score | rank |
+--------+-------+------+
|1002|99
|1||
1003|96
|2||
1004|96
|2||
1008|94
|4||
1005|92
|5||
1006|90
|6||
1007|90
|6||
1001|89
|8|+
--------+-------+------+
上面介紹了三種排名方式,實現起來還是比較複雜的。好在mysql8.0增加了視窗函式,使用內建函式可以輕鬆實現上述排名。
mysql8.0中可以利用 row_number(),dense_rank(),rank() 三個視窗函式實現上述三種排名,需要注意的一點是as後的別名,千萬不要與前面的函式名重名,否則會報錯,下面給出這三種函式實現排名的案例:
# 三條語句對於上面三種排名
select xuehao,score, row_number(
)over
(order
by score desc
)as row_r from scores_tb;
select xuehao,score, dense_rank(
)over
(order
by score desc
)as dense_r from scores_tb;
select xuehao,score, rank(
)over
(order
by score desc
)as r from scores_tb;
# 一條語句也可以查詢出不同排名
select xuehao,score,
row_number(
)over w as
'row_r'
, dense_rank(
)over w as
'dense_r'
, rank(
)over w as
'r'from
`scores_tb`
window w as
(order
by`score`
desc);
# 排名結果
+--------+-------+-------+---------+---+
| xuehao | score | row_r | dense_r | r |
+--------+-------+-------+---------+---+
|1002|99
|1|1
|1||
1003|96
|2|2
|2||
1004|96
|3|2
|2||
1008|94
|4|3
|4||
1005|92
|5|4
|5||
1006|90
|6|5
|6||
1007|90
|7|5
|6||
1001|89
|8|6
|8|+
--------+-------+-------+---------+---+
本文給出三種不同場景下實現統計排名的sql,可以根據不同業務需求選取合適的排名方案。對比mysql8.0,發現利用視窗函式可以更輕鬆實現排名,其實業務需求遠遠比我們舉的示例要複雜許多,用sql實現此類業務需求還是需要慢慢積累的。 教你用SQL實現統計排名
前言 在某些應用場景中,我們經常會遇到一些排名的問題,比如按成績或年齡排名。排名也有多種排名方式,如直接排名 分組排名,排名有間隔或排名無間隔等等,這篇文章將總結幾種mysql中常見的排名問題。建立測試表 create table scores tb id int auto increment pr...
SQL成績統計分析 排名問題
select from studentscore select row number over order by studentscore desc,id desc number,from studentscore 下面介紹下在sql成績統計分析中遇到的一些小問題,首先介紹下成績分析中經常遇到的問題...
Sql排名和分組排名
在很多時候,都有排名這個功能,比如排行榜,並且還需要分頁的功能,一般可以再select的時候按照某一字段 oorder by xx desc,這樣limit 查詢就可以得到排名資訊,但是有時候是需要多表連線,或者是有乙個隨機檢視,在頁面上並不是按照排名公升降序。這個時候就需要用sql來實現排名。先準...