我需要获得顶级球员,一名球员的排名以及少数排名靠前的球员。
为了更清楚地解释,下面的表是我想要的,它按分数显示前3名球员,给定球员的等级(id = 11)和2名得分刚好超过给定球员的球员:
+----+------+-------+--------+------+
| id | name | score | @rk:=0 | rank |
+----+------+-------+--------+------+
| 7 | g | 31 | 0 | 1 |
| 8 | h | 29 | 0 | 2 |
| 9 | i | 28 | 0 | 3 |
| 4 | d | 23 | 0 | 8 |
| 11 | k | 21 | 0 | 9 |
| 1 | a | 20 | 0 | 10 |
+----+------+-------+--------+------+
样本数据:
CREATE TABLE test (
id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(20),
score int
);
INSERT INTO test (name,score) VALUES ("a", 20),("b", 19),("c", 23),("d", 23),
("e", 27),("f", 25),("g", 31),("h", 29),("i", 28),("j", 24),("k", 21);
我已经设法显示排名,顶级球员,给定球员:
SELECT id,name,score,rank FROM
(SELECT *,@rk:=@rk+1 AS rank FROM test, (SELECT @rk:=0) r WHERE 1 ORDER BY score DESC) AS s
WHERE rank<=3 OR id=11 ORDER BY rank ASC
结果:
+----+------+-------+------+
| id | name | score | rank |
+----+------+-------+------+
| 7 | g | 31 | 1 |
| 8 | h | 29 | 2 |
| 9 | i | 28 | 3 |
| 11 | k | 21 | 9 |
+----+------+-------+------+
我很难展示那些在给定球员身上得分(高于或低于id = 4且id = 1)的球员。
我更喜欢1 sql查询,考虑到性能,因为数据可能很大。
答案 0 :(得分:0)
我找到了解决问题的方法。为了找到得分球员,我首先尝试查询(中间部分 - s2和s3)给定球员的排名,存储在varian @givenrank中。 mysql查询如下:
SELECT id,name,rank FROM
(SELECT *,@rk:=@rk+1 AS rank FROM test, (SELECT @rk:=0) r WHERE 1 ORDER BY score DESC) AS s,
(SELECT @givenrank:=rank2 FROM
(SELECT *,@rk2:=@rk2+1 AS rank2 FROM test, (SELECT @rk2:=0) r2 ORDER BY score DESC) AS s2
WHERE id=11) AS s3
WHERE rank<=3 OR (@givenrank-1<=rank AND rank<=@givenrank+1) OR id=11 ORDER BY rank ASC;
结果正是我想要的:
+----+------+------+
| id | name | rank |
+----+------+------+
| 7 | g | 1 |
| 8 | h | 2 |
| 9 | i | 3 |
| 4 | d | 8 |
| 11 | k | 9 |
| 1 | a | 10 |
+----+------+------+
一些新问题:
为解决第二个问题,我将查询分为两个,如下所示。首先查询rank varian,如果为null,则不会影响结果。它适用于两种情况(给定的玩家在表中有或没有记录)。但是,使用两个查询不是我喜欢的解决方案(我更喜欢1个查询)。有什么想改进吗?
SELECT @givenrank:=rank2 FROM
(SELECT *,@rk2:=@rk2+1 AS rank2 FROM test, (SELECT @rk2:=0) r2 ORDER BY score DESC) AS s2
WHERE id=11;
SELECT id,name,rank FROM
(SELECT *,@rk:=@rk+1 AS rank FROM test, (SELECT @rk:=0) r WHERE 1 ORDER BY score DESC) AS s
WHERE rank<=3 OR (@givenrank IS NOT NULL AND @givenrank-1<=rank AND rank<=@givenrank+1) OR id=11 ORDER BY rank ASC;