MySQL实现排名

1,024 阅读3分钟

排名在我们日常生活中并不陌生,例如玩游戏的分数等等排名,都需要用到SQL语句查询数据库。不过具体怎么通过SQL语句实现排名呢?

为了举例说明,我先随便定义一个表和一些数据,以便于下面的查询:

create table `playertable` (
	`id` bigint not null,
	`nickname` varchar(32) not null,
	`age` int not null,
	`score` int not null,
	primary key (`id`)
) engine=InnoDB default charset=utf8mb4;
 
insert into `playertable`
(id, nickname, age, score)
values
(1, "test", 17, 192),
(2, "dev", 11, 12),
(3, "asa", 27, 34),
(4, "err", 34, 112),
(5, "admin", 11, 2233),
(6, "lkkka", 23, 432),
(7, "pop", 71, 675),
(8, "asddw", 33, 23),
(9, "root", 24, 908),
(10, "qwe", 12, 233),
(11, "zxc", 23, 452),
(12, "jkalso", 45, 123),
(13, "plomo", 23, 231),
(14, "llkknsadsa", 7, 659);

1,基本知识

在这个教程中需要涉及到一点基本的知识先在此带一下。

(1) as语句

用于定义别名。表和变量都可以定义别名。其中表定义别名时可以省略as,例如:

(select * from playertable) as t;
(select * from playertable) t;

都是把查询得到的结果定义为了t

(2) 派生表

我们每做一次的select的操作得到的结果都可以作为一个临时的派生表,我们甚至还可以在这个派生表里面进行进一步查询进行数据筛选。例如我从上述玩家表中年龄从小到大的前十名中进一步筛选出分数从高到低的前五名的昵称、年龄、分数信息:

select nickname, age, score from (select * from `playertable` order by age limit 10) as temp order by score desc limit 5;

结果:

image.png

我们可以先看括号部分,意思是先选择玩家表中的年龄从小到大的前十个作为派生表,并给其别名为temp。这样派生表就定义出来了。一般括号会被优先执行,可以将其当做一个整体。

再进一步筛选就是括号外大部分语句了!注意派生表必须要有别名!

具体分解可以看图:

image.png

(3) MySQL中的@符号

可以自定义一个临时变量。通过以下语句设定临时变量:

set @变量名 := 变量值;
 
//或者
(select @变量名 := 变量值) as temp;

2,具体实现

基本思路就是,定义一个名为row的变量用于表示当前排名,再定义两个临时派生表,一个派生表主要是用于row变量的初始化,且这个表只有一个字段,那就是row,且每一条记录row的值就会加一,另一个派生表就是我们查询玩家数据并排序得到的结果。最后将这两个派生表组合起来不就行了吗?

例如选择分数前五名玩家并排名:

select nickname, score, @row := @row + 1 as sequence from (select @row := 0) as ranktable, (select * from `playertable` order by score desc limit 5) as playerinfo;

结果:

image.png

语句分解如下:

image.png

加上where语句还可以查询具体玩家的名次:

select nickname, score, @row := @row + 1 as sequence from (select @row := 0) as ranktable, (select * from `playertable` order by score desc limit 5) as playerinfo where nickname="admin";

结果:

image.png