17

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

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

我希望 Ranking 字段根据谁的得分最高包含 1、2、3,所以结果应该是:

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

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

4

6 回答 6

25

这是一种方法:

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;
于 2010-07-07T17:12:35.893 回答
6

在 MySQL 中,您可以使用 row_number

这是在 a 中使用它的示例SELECT

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

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

于 2010-07-07T16:53:35.840 回答
5

This creates an inline update statement that will rank your players incrementing by the variable @rc. I've used it many times in very similar cases, it works well and keeps it all on the DB side.

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 is assumed to be the primary key for your players table.

于 2010-07-07T17:03:53.817 回答
2
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;
于 2013-01-04T07:28:53.490 回答
2

如果您使用的是 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
于 2020-12-15T12:33:43.417 回答
1

我正在向您展示我的做法[对于间隔 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`

除了测试它是否有效外,我没有对此进行任何性能检查

于 2012-11-07T13:17:23.570 回答