我使用以下SQL在排行榜表中按排名排序:
SELECT score, 1+(SELECT COUNT(*) FROM leaderboard a WHERE a.score > b.score) AS rank
FROM leaderboard b
WHERE stage=1
GROUP BY id
我的表架构是这样的:
CREATE TABLE `leaderboard` (
`auto_id` int(11) NOT NULL AUTO_INCREMENT,
`score` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL,
`created_on` datetime NOT NULL,
PRIMARY KEY (`auto_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
一些示例数据行如下:
auto_id score id created_on
====================================================
1, 72023456, 1, '2014-12-30 11:49:59'
2, 1420234, 1, '2014-12-30 12:00:21'
3, 420234, 1, '2014-12-30 12:00:38'
4, 16382, 1, '2014-12-30 16:31:12'
5, 16382, 1, '2014-12-30 16:34:18'
6, 16382, 1, '2014-12-30 16:37:43'
7, 17713, 1, '2014-12-30 16:38:35'
8, 17257, 1, '2014-12-30 18:53:45'
9, 10625, 1, '2014-12-30 18:58:10'
10, 17272, 1, '2014-12-30 18:58:59'
11, 17328, 1, '2014-12-30 18:59:44'
12, 17267, 37, '2015-01-02 17:11:59'
13, 16267, 37, '2015-01-02 17:12:30'
14, 16267, 37, '2015-01-02 17:13:02'
15, 35509, 37, '2015-01-02 17:17:46'
16, 18286, 37, '2015-01-02 18:20:09'
17, 16279, 37, '2015-01-02 18:20:43'
18, 16264, 37, '2015-01-02 18:21:15'
19, 16265, 37, '2015-01-02 18:40:04'
由于id
是玩家的ID,我必须GROUP BY id
。它给出了以下结果:
id score rank
=========================
1 72023456 1
37 17267 11
如何获得以下预期结果?
id score rank
=========================
1 72023456 1
37 35509 2
目前的问题是,现有结果不是玩家的最高得分。
奖励:我的最终目标是让参赛作品获得1等排名。比特定id
低1个等级。
答案 0 :(得分:2)
由于MySql没有Windowing Functions
您需要的查询必须模仿其行为,因此您必须使用变量。
select id, score, @rank :=@rank+1 as rank
from (
SELECT b.id, max(b.score) as score
FROM leaderboard b
GROUP BY id
order by score desc
) tab
,(select @rank := 0) r
编辑:我犯了一个小错误。我现在已经纠正过了。
输出将是:
id score rank
=========================
1 72023456 1
37 35509 2
基本上我正在做的是在查询上创建一个迭代器,并且每行都会增加变量。当我添加订单时,它将根据该订单对您的值进行排名。但是这个等级必须在查询之外发生,因为如果有两个以上的ID,那么顺序与等级并列将会搞砸了
我将使用" 1等级更高的解决方案编辑查询。比特定身份低1个等级。"
编辑奖金(虽然不漂亮)
select id, score, rank
from (
select tab.id, tab.score, @rank :=@rank+1 as rank
from (select @rank := 0) r,
(SELECT b.id, max(b.score) as score
FROM leaderboard b
GROUP BY id
order by score desc) tab
) spec
where spec.id=2
UNION
select id, score, rank
from (
select tab.id, tab.score, @rank :=@rank+1 as rank
from (select @rank := 0) r,
(SELECT b.id, max(b.score) as score
FROM leaderboard b
GROUP BY id
order by score desc) tab
) spec
where spec.rank=
(select rank-1
from (
select tab.id, tab.score, @rank :=@rank+1 as rank
from (select @rank := 0) r,
(SELECT b.id, max(b.score) as score
FROM leaderboard b
GROUP BY id
order by score desc) tab
) spec
where spec.id=2)
UNION
select id, score, rank
from (
select tab.id, tab.score, @rank :=@rank+1 as rank
from (select @rank := 0) r,
(SELECT b.id, max(b.score) as score
FROM leaderboard b
GROUP BY id
order by score desc) tab
) spec
where spec.rank=
(select rank+1
from (
select tab.id, tab.score, @rank :=@rank+1 as rank
from (select @rank := 0) r,
(SELECT b.id, max(b.score) as score
FROM leaderboard b
GROUP BY id
order by score desc) tab
) spec
where spec.id=2)
order by rank;
请注意,您将特定ID放在条款spec.id=2
上(我已经放2,因为我必须更改环境中的值以进行测试)
这里的SQL Fiddle和我的测试,两个查询工作:http://sqlfiddle.com/#!2/75047/2
答案 1 :(得分:0)
得分不是最大值的原因是,因为得分不在GROUP BY
子句中,所以MySQL只是选择第一个值作为代表。从技术上讲,这不是有效的SQL。您可能想要使用MAX(score) AS score
。
至于排名,由于MySQL不支持窗口功能,你必须自己破解。您可以查看this SO post了解更多信息。标准方法似乎是使用可变变量来计算行,或者使用ON
子句中的不等式将查询连接到自身。看起来都不是很优雅。