简体   繁体   English

根据行的数值更新

[英]Updating based on numerical value of a row

I need to make a point system in MySQL, the points are added based on the position of a certain column. 我需要在MySQL中创建一个点系统,这些点是根据特定列的位置添加的。 Example: there are 5 players, the player with the highest score in "Conqueror" row gets awarded 5 points, the 2nd player gets awarded 4 points, the 3rd player 3 points etc. This is a stored procedure that I would call when calculating points: 示例:有5位玩家,“征服者”行中得分最高的玩家获得5分,第二位获得4分,第三位获得3分,等等。这是一个存储过程,在计算得分时会调用:

BEGIN
select Player_name into @a from Player where Conqueror = (select max(Conqueror) from Player);
select Player_name into @b from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a);
select Player_name into @c from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a and Player_name != @b );
select Player_name into @d from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a and Player_name !=@b and Player_name !=@c);
select Player_name into @e from Player where Conqueror = (select max(Conqueror) from Player where Player_name != @a and Player_name !=@b and Player_name !=@c and Player_name !=@d );
select count(Conqueror) into @playernum from Player;
update Player set Points = Points + @playernum where Player_name = @a;
update Player set Points = Points + @playernum-1 where Player_name = @b;
update Player set Points = Points + @playernum-2 where Player_name = @c;
update Player set Points = Points + @playernum-3 where Player_name = @d;
update Player set Points = Points + @playernum-4 where Player_name = @e;
END

This code looks terrible but it works fine except when there are players with the same score. 该代码看起来很糟糕,但是除了有得分相同的玩家外,它的工作原理还不错。 In that case an MySQL Error #1172 - Result consisted of more than one row due to two or more Player_name's are being added to a variable. 在那种情况下,由于两个或多个Player_name被添加到变量中,导致MySQL错误#1172-结果包含多行。 Can anyone please give me an idea on how to solve this? 谁能给我一个解决方法的想法?

I haven't had time to play with it and come up with a solution where Player 4 gets 2 points instead of 3, but it's probably just a case of adding an extra bit to the IF statement. 我没时间玩,想出了一个解决方案,玩家4得到2分而不是3分,但这可能只是在IF语句中增加一点点的一种情况。 But based on this blog post: 但是根据此博客文章:

http://jimmod.com/blog/2008/09/09/displaying-row-number-rownum-in-mysql/ http://jimmod.com/blog/2008/09/09/displaying-row-number-rownum-in-mysql/

I would actually get rid of the stored procedure and do the whole thing in one update statement with a subselect. 实际上,我将摆脱存储过程,并在一个带有subselect的update语句中完成整个操作。 Something like (completely untested!): 有点像(完全未经测试!):

update Player set points =
  ( select points from
      ( SELECT @rownum:=@rownum-1 'points', Conqueror FROM Player p, 
          (SELECT @rownum:=6) r 
        order by Conqueror desc
      )
  )

This should, if I've guessed the syntax right, allocate 5 to the highest, 4 to the second, etc except if two players have the same points, one will get 4 and the other will get 3. Check the blog post for an IF statement that will solve this - I'll take a look later when I have more time :) 如果我猜对了语法,那么应该这样做,将5分配到最高点,将4分配给第二点,依此类推,除非两个玩家的得分相同,一个将得到4,另一个将得到3。 IF语句将解决此问题-我将在有更多时间时查看:)

EDIT 编辑

In case the blog ever gets taken down, this is the IF statement I am referring to: 万一博客被删除,这就是我指的IF语句:

select IF(@score=p.score, @rownum, @rownum:=@rownum+1) rank2, p.*, (@score:=p.score) dummy from player p, 
(SELECT @rownum:=0) x, 
(SELECT @score:=0) y 
order by score desc limit 10;

If you don't need to place users with the same Conqueror on the same place you can use this ONE query :-) not 5. 如果您不需要将具有相同Conqueror用户放在同一位置,则可以使用此ONE查询:-)而不是5。

updated query already allow users to have the same Conqueror values and they will be granted same amount of points according to your comment : 更新的查询已经允许用户拥有相同的Conqueror值,并且根据您的评论,他们将被授予相同数量的积分:

Ideally, lets say that player number 2 and 3 have the same score. 理想情况下,假设2号和3号选手得分相同。 Player 2 gets awarded 4 points and player 3 also 4 points but player 4 would get rewarded 2 points. 玩家2获得4分,玩家3也获得4分,但玩家4将获得奖励2分。 So when there are same scores all the players get awarded the points as if they were the only ones with that score. 因此,当分数相同时,所有玩家都将获得积分,就好像他们是唯一拥有该分数的玩家一样。 – Voodoo –巫毒教

SET @rank = 6;
UPDATE Player 
INNER JOIN 
(
  SELECT player_id,
    @rank := @rank-1 as rank,
    CASE WHEN @prev = Conqueror 
      THEN @correction := @correction+1 
      ELSE @correction := 0  
    END as correction,
    @prev := Conqueror
  FROM Player
  ORDER BY Conqueror DESC
  LIMIT 5
) as r
ON Player.player_id = r.player_id
SET Points = Points + r.rank + r.correction;

And if you need to place players with the same Conqueror result on the same rank, just give me more rules how to handle such situations. 而且,如果您需要将具有相同Conqueror结果的玩家放在同一排名上,请给我更多规则以处理此类情况。

EDIT - EXPLANATION 编辑-说明

Cauze you commented you don't understand what is going on in my query, I'll try to explain a little. 告诫您,您不了解我的查询中发生了什么,我将尝试解释一下。

So @prev var holds the value of previous top player executed. 因此, @prev var保留先前执行的顶级玩家的值。

For example for the player who has 2nd rank it will hold the Conqueror value of the 1st player. 例如,对于排名第二的玩家,它将保留第一位玩家的Conqueror值。

We need it to compare if 2nd place player has the same score as 1st to give him same amount of points as you asked in your comment. 我们需要比较一下第二名玩家是否具有与第一名相同的分数,以便为他提供与您在评论中要求的分数相同的分数。

r.rank and r.correction holds the RANK (points/place from 5 to 1) for the player that you want to add to Points field. r.rankr.correction保留您要添加到“ Points字段中的玩家的排名(点数/位置,从5到1)。 And correction is stands for correct those value if players have same Conqueror and we need to give the same amount of points even if rank are 2 and 3 for example but points added will be the same rank=4 + correction=0 for 2nd player and rank=3 + correction=1 for 3rd player 如果玩家拥有相同的Conqueror ,则校正代表对这些值的校正,并且即使排名为2和3,我们也需要给出相同的点数,但是对于第二名玩家,添加的点数将是相同的等级= 4 +校正= 0第三名玩家的等级= 3 +修正= 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM