我有一个排名,每个X时间都有一个余额添加到每个玩家的总分数,改变他们的排名方式。 我希望我的排名是在DB(MySQL)上计算的,但我希望它是高效的,所以首先要做的是,这里是BalanceIn代码:
Q1:
UPDATE playerscore
SET points = points * 0.9 + GREATEST(-100, LEAST(100, balance)),
balance = 0;
一旦points
为所有人更新,我想重新排序等级(仅限排名玩家),如下:
Q2:
SET @r = 0;
UPDATE playerscore p
INNER JOIN
(SELECT @r:=@r+1 as new_rank, player_id
FROM playerscore
WHERE is_ranked = 1
ORDER BY points DESC) s
ON p.player_id = s.player_id
SET p.rank = s.new_rank
WHERE is_ranked = 1;
它有效,并且解决了我的问题,但是:这是进行1选择,从这里更新所有值,还是会为每个玩家核心行选择?
在伪代码中,这就是我不想要的东西:
foreach PlayerScore p in playescore
new = get_all_players_sorted
update p.rank = new.new_rank where p.player_id = new.player_id
endforeach
对于N个玩家:N选择+ N个更新。 我希望它是:1选择+ N更新(包含在单个更新中),如下所示:
new = get_all_players_sorted
foreach PlayerScore p in playescore
update p.rank = new.new_rank where p.player_id = new.player_id
endforeach
我的查询是否正确(Q2)??
答案 0 :(得分:1)
如果这是您的查询,您可以通过重新构造查询并使用索引来加快速度。
您想要的索引是playerscore(is_ranked, points desc)
。查询是:
SET @r = 0;
UPDATE playerscore p
SET p.rank = (@r := @r + 1)
WHERE is_ranked = 1
ORDER BY points desc;
在MySQL中,只要您没有使用order by
,就可以将update
与join
一起使用。在这种情况下,您不需要join
,因为您将变量设置为单独的语句。