计算PHP / MySQL中的排名

时间:2011-01-30 20:26:32

标签: php mysql ranking

我在MySQL中有一个表只是说例如它有两个字段Username,GameName和Score。 我想计算一个单独游戏名称的用户等级,以便我可以进行查询

SELECT * FROM scores WHERE `GameName` = 'Snake' ORDER BY `Score` DESC

按从高到低的顺序获取所有用户的列表,并为每个用户分配一个号码。

但是,有一种更简单的方法来获得单个用户的排名,而不是选择整个表格,因为这看起来效率不高。

由于

8 个答案:

答案 0 :(得分:4)

如果你想要整体排名,不幸的是你必须对整个表格进行排序。简单地说,如果不知道表中的其他等级,你就无法知道某人的排名。

那就是说,如果你担心性能,这里有一个相当容易的解决方案 - 缓存你的排名查询的结果(可能是另一个MySQL表!),并查询你的所有读取。当有人发布新分数时,重新计算临时表。您可以定期刷新某个等级以下的所有记录(例如,排名低于100的任何人从分数表中删除)以保持重新计算的速度,因为在被较高分数击倒后没有人会升级。

# Create your overall leaderboards once
create table leaderboards (rank integer primary key, score_id integer, game varchar(65), user_id integer, index game_user_id_idx (game, user_id))


# To refresh your leaderboard, we'll query the ranks for the game into a temporary table, flush old records from scores, then copy
# the new ranked table into your leaderboards table.
# We'll use MySQL's CREATE TABLE...SELECT syntax to select our resultset into it directly upon creation.
create temporary table tmp_leaderboard (rank integer primary key auto_increment, score_id integer, game varchar(65), user_id integer)
  select ID, GameName, UserID, from scores where GameName = '$game' order by score desc;

# Remove old rankings from the overall leaderboards, then copy the results of the temp table into it.
delete from leaderboards where game = '$game';
insert into leaderboards (rank, score_id, game, user_id)
  select rank, score_id, game, user_id from tmp_leaderboard;

# And then clean up the lower scores from the Scores table
delete from scores join tmp_leaderboard on scores.id = tmp_leaderboard.score_id, scores.GameName = tmp_leaderboard.game where tmp_leaderboard.rank < 100;

# And we're done with our temp table
drop table tmp_leaderboard;

然后,每当你想要阅读游戏的等级时:

select rank from leaderboards where game = '$game' and user_id = '$user_id';

答案 1 :(得分:1)

从您的users表中获取用户ID并在查询中使用它


SELECT * FROM scores WHERE `GameName` = 'Snake' 
and `youruseridfield` = '$useridvalue'
ORDER BY `Score` DESC

答案 2 :(得分:1)

SELECT * FROM scores WHERE 'GameName' = 'Snake' && userID = '$userID' ORDER BY 'Score' DESC

答案 3 :(得分:1)

有趣的是看看是否有办法获得MySQL的排名,但这里是你如何在PHP中做到这一点:

function getRank($user, $game, $limit=50) {
    $sql = "
SELECT @rank:=@rank+1 AS Rank, User, GameName
FROM scores, (SELECT @rank:=1) AS i
WHERE `GameName` = '$game' 
ORDER BY `Score` DESC
LIMIT 0, $limit
";

    $result =  mysql_query($sql);

    while ($row = mysql_fetch_assoc($result)) {
        if ($row['User'] == $user) {
            return $row['Rank'];
        }
    }

    return -1;
}

注意,我把限制放在那里,否则你不会得到30个结果。如果玩家没有受到限制,它会返回-1。

答案 4 :(得分:1)

您无法远离阅读表格中的大量数据 - 但您无需将其一直拖回处理脚本:

SELECT COUNT(*)
FROM scores 
WHERE `GameName` = 'Snake'
AND user=$some_user;

(因为你可能希望第一个人的排名为'1'而不是'0',所以增加结果。)

但是,如果您需要经常运行查询,则值得维护已排序结果的物化视图。

答案 5 :(得分:1)

我的一个查询解决方案:

select @rank:=@rank+1 AS Rank,L1.* from 
    (select @rank:=0) as L2,
    (select i.*,count(*) as sum 
        FROM 
        transactions t
        LEFT JOIN companies c on (c.id = t.company_id)  
        LEFT JOIN company_industries ci on (c.id = ci.company_id)  
        LEFT JOIN industries i on (ci.industry_id = i.id)
        GROUP by i.name 
        ORDER BY sum desc ) as L1;

答案 6 :(得分:0)

您应该为GameName和Score添加索引。 (并且在插入查询之前不要忘记逃避GameName =&gt; mysql_real_escape_string)。 @Bryan:不应该是“AND”而不是“&amp;&amp;” ?

答案 7 :(得分:0)

以下查询使用的是排名函数,这也可以实现:

WITH game_rank AS(
    SELECT 
        user_id, 
        gameName, 
        RANK() OVER (
            PARTITION BY gameName
            ORDER BY score DESC
        ) order_value_rank
    FROM
        scores
)
SELECT 
    * 
FROM 
    game_rank
WHERE 
    gameName = "Snake";