【问题标题】:MySQL update statement to store ranking positionsMySQL更新语句存储排名位置
【发布时间】:2010-07-07 16:45:18
【问题描述】:

我正在努力解决一个问题,但我就是想不通。如果有人给我指点,我将不胜感激。作为我想要实现的一个简单示例,我在数据库中有这些记录

Score|Ranking
-------------
100  |0
200  |0
300  |0

我希望排名字段包含 1、2、3,基于谁获得了最高分,所以结果应该是:

Score|Ranking
-------------
100  |3
200  |2
300  |1

目前,我正在为所有这些记录执行 for next 循环,但考虑到实际上可能有几千个 - 这可能需要很长时间!有没有人有一个魔术查询的想法,可以一次性做到这一点?

【问题讨论】:

    标签: mysql sql sql-update ranking


    【解决方案1】:

    这是一种方法:

    SET @r=0;
    UPDATE table SET Ranking= @r:= (@r+1) ORDER BY Score DESC;
    
    /* use this if you just want to pull it from the db, but don't update anything */
    SET @r=0;
    SELECT *, @r:= (@r+1) as Ranking FROM table ORDER BY Score DESC;
    

    【讨论】:

    • 查看 DOK 的版本 - 它不需要 SET 语句,它是完全独立的。
    • 在单个查询中是自包含的,是的;但那是因为他在 SELECT 子查询中设置了@rownum。我认为这看起来更混乱。
    • 美女在旁观者眼中,但能提交单一陈述的可能性较小
    • 我认为这应该按升序排序?
    【解决方案2】:

    在 MySQL 中,您可以使用 row_number

    Here's an exampleSELECT 中使用它:

    select @rownum:=@rownum+1 ‘rank’, p.* 
    from player p, (SELECT @rownum:=0) r 
    order by score desc;
    

    如果你INSERT INTO 像这样使用SELECT,你就会得到你的排名。

    【讨论】:

    • +1:通常我会说这应该在视图中,但 MySQL 视图不允许使用变量。有一种替代方法在子选择中使用 COUNT 来获取在我想象的视图中可以使用的排名值...
    【解决方案3】:

    这将创建一个内联更新语句,该语句将按变量 @rc 递增对您的玩家进行排名。我在非常相似的情况下多次使用过它,它运行良好,并将其全部保存在数据库端。

    SET @rc = 0;
    UPDATE players JOIN (SELECT @rc := @rc + 1 AS rank, id FROM players ORDER BY rank DESC)
    AS order USING(id) SET players.rank = order.rank;
    

    id 被假定为您的players 表的主键。

    【讨论】:

      【解决方案4】:
      SET @r = 0;
      UPDATE players JOIN (SELECT @r := @r + 1 AS rank, id FROM players ORDER BY rank DESC)
      AS sorted USING(id) SET players.rank = sorted.rank;
      

      【讨论】:

        【解决方案5】:

        如果您使用的是 MySQL 8,那么您可以使用新功能RANK()

        SELECT
            score,
            RANK() OVER (
               ORDER BY score DESC
            ) ranking
        FROM
            table;
        

        取决于您希望如何显示具有偶数的排名,所以您也可以查看DENSE_RANK()

        作为更新:

        WITH
           ranking AS(
           SELECT
              score,
              RANK() OVER (
                 ORDER BY score DESC
              ) ranking
            FROM
                table
        )
        UPDATE
            table,
            ranking r
        SET
            table.ranking = r.ranking
        WHERE
            table.score = r.score
        

        【讨论】:

          【解决方案6】:

          我正在向你展示我的做法[对于间隔 sql 更新函数]

          选择:

          set @currentRank = 0,
              @lastRating = null,
              @rowNumber = 1;
          select
              *,
              @currentRank := if(@lastRating = `score`, @currentRank, @rowNumber) `rank`,
              @rowNumber := @rowNumber + if(@lastRating = `score`, 0, 1) `rowNumber`,
              @lastRating := `score`
          from `table`
          order by `score` desc
          

          更新:

          set @currentRank = 0,
              @lastRating = null,
              @rowNumber = 1;
          update 
              `table` r
              inner join (
                  select
                      `primaryID`,
                      @currentRank := if(@lastRating = `score`, @currentRank, @rowNumber) `rank`,
                      @rowNumber := @rowNumber + if(@lastRating = `score`, 0, 1) `rowNumber`,
                      @lastRating := `score`
                  from `table`
                  order by `score` desc
              ) var on
                  var.`primaryID` = r.`primaryID`
          set
              r.`rank` = var.`rank`
          

          除了测试它的工作原理之外,我没有对此进行任何性能检查

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-16
            • 1970-01-01
            • 2010-11-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多