MYSQL,SQL语句题目:
试验用的简书上的一个数据表脚本:
CREATE TABLE `players` ( `pid` int(2) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `age` int(2) NOT NULL, PRIMARY KEY (`pid`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB;
INSERT INTO `players` (`pid`, `name`, `age`) VALUES (1, 'Samual', 25), (2, 'Vino', 20), (3, 'John', 20), (4, 'Andy', 22), (5, 'Brian', 21), (6, 'Dew', 24), (7, 'Kris', 25), (8, 'William', 26), (9, 'George', 23), (10, 'Peter', 19), (11, 'Tom', 20), (12, 'Andre', 20);
实现:
1.排名不跳级,按顺序排序下来:
select p.pid,p.name,p.age,tmp.rank1 from players p
left join (select a.age,@rank :=@rank + 1 as rank1
from (select age from players group by age) a ,(select @rank:=0) tmp ORDER BY a.age
desc ) tmp on p.age=tmp.age order by p.age desc,p.name desc;
这是基本的实现方式,但是如果players表数据过大,里面包含了子表嵌套查询,表连接会影响执行的效率。
我想的最佳实现方式可能是:
select p.pid,p.name,p.age,
case when @curentValue =p.age THEN @currank
when @currentValue := p.age THEN @currank := 1+@currank end as currentRank, @curentValue := p.age
from players p , (select @currank := 0,@curentValue :=null) tmp
order by p.age desc,p.name desc
2.排名跳级
select p.pid,p.name,p.age,
case when @curentValue =p.age THEN @currank
when @currentValue := p.age THEN @currank := 1+@jumpRank end as currentRank, @curentValue := p.age, @jumpRank := @jumpRank +1
from players p ,
(select @currank := 0,@jumpRank := 0,@curentValue :=null) tmp
order by p.age desc,p.name desc
至于第一种实现方式会不会产生笛卡尔积,参看blog:https://blog.csdn.net/zy_281870667/article/details/81046573
抛开笛卡尔积不说,我认为起码第一种实现方式,表连接是会导致查询效率变低的。
还有个坑爹的地方:
我用的mysql版本8.0.12.。。。。写sql开始用的AS rank, 报错了!