sql如何實現百分比統計 教你用SQL實現統計排名

2021-10-11 23:13:24 字數 4016 閱讀 9235

前言:

在某些應用場景中,我們經常會遇到一些排名的問題,比如按成績或年齡排名。排名也有多種排名方式,如直接排名、分組排名,排名有間隔或排名無間隔等等,這篇文章將總結幾種mysql中常見的排名問題。

建立測試表

create table scores_tb (    id int  auto_increment primary key,    xuehao int not null,     score int not null) 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.普通排名

按分數高低直接排名,從1開始,往下排,類似於row number。下面我們給出查詢語句及排名結果。

# 查詢語句select xuehao, score, @currank := @currank + 1 as rankfrom scores_tb, (select @currank := 0) rorder 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 |+--------+-------+------+
上述查詢語句中,我們申明了乙個變數 @currank ,並將此變數初始化為0,查得一行將此變數加一,並以此作為排名。我們看到這類排名是沒間隔的並且有些分數相同但排名不同。

2.分數相同,名次相同,排名無間隔

# 查詢語句select xuehao, score, case when @prevrank = score then @currank when @prevrank := score then @currank := @currank + 1end as rankfrom 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    |+--------+-------+------+
3.並列排名,排名有間隔

另外一種排名方式是相同的值排名相同,相同值的下乙個名次應該是跳躍整數值,即排名有間隔。

# 查詢語句select xuehao, score, rank from(select xuehao, score,@currank := if(@prevrank = score, @currank, @incrank) as rank, @incrank := @incrank + 1, @prevrank := scorefrom 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 利用視窗函式實現排名

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 總合百分比

算出累積總計是乙個常見的需求,可惜以 sql 並沒有乙個很直接的方式達到這個需求。要以 sql 算出累積總計,基本上的概念與列出排名類似 第一是先做個 自我鏈結 self join 然後將結果依序列出。在做列出排名時,我們算出每一行之前 包含那一行本身 有多少行數 而在做累積總計時,我們則是算出每一...

sql操作歸類百分比

原資料 專案名稱 完成否 主閘 是 主閘 是 主閘 否 發動機 是 發動機 否 發動機 否 鏈條 是 鏈條 是 鏈條 否 想要得到的資料 專案名稱 完成百分比 主閘 2 3 發動機 1 3鏈條 2 3sql語句應該如何寫?select name,convert varchar 100 sum cas...

sql語句求百分比

此sql語句包括了兩個聚合函式做除法求百分比,並保留兩位小數,直接輸出字串形式的百分比。以及對case when在聚合函式的應用。select ss.ss name,ss id,count ea.ea id as eacounts,回單交換單個數 count eb.eb id as ebcounts...