2014-09-26 38 views
1

我有一个排名,每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:[email protected]+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; 

它的工作原理,解决了我的p但是:这是为了让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)做这件事?

回答

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 byupdate - 因为你没有使用join长。在这种情况下,您不需要join,因为您将该变量设置为单独的语句。

+0

真的很好,很快!用100k寄存器进行测试,并花费不到一秒钟来完成'Q1' +'Q2' :) – 2014-09-26 11:07:26