【问题标题】:How to optimize a score/rank table with different specific scores and ranks?如何优化具有不同特定分数和排名的分数/排名表?
【发布时间】:2013-09-15 17:30:23
【问题描述】:

在我们的项目中,我们有一个用户表,其中存储了包含名称和不同类型分数(总分数、任务分数等)的用户数据。值的计算方式无关紧要,但请将它们视为单独的。

让我们看看下面的表格“用户”

  id   name   score_overall   score_trade   score_quest    

  1    one    40000           10000         20000
  2    two    20000           15000         0
  3    three  30000           1000          50000
  4    four   80000           60000         3000

为了显示分数,有一个虚拟表和一个表,用于存储用户名以及分数和排名的每种分数。所有表看起来都一样,但名称不同。

id  name  score  rank  

它们是分开的,以允许用户搜索和过滤表格。假设有一行玩家“playerX”的排名为 60。因此,如果我过滤“playerX”的分数,我只会看到这一行,但排名为 60。这意味着排名是“硬存储”的,不仅通过行号或类似的东西动态显示。

不同的分数表是通过 cronjob 填充的(并在使用附加的虚拟表的情况下),它执行以下操作:

  1. 将用户数据复制到虚拟表中
  2. 通过order by score 更改虚拟表
  3. 将虚拟表复制到特定的分数表,以便 AI 主键(排名)自动填充正确的值,代表每个用户的排名。

也就是说:有五个具体分数的地方,还有五个分数表和虚拟表,一共是6个。

如何优化?

我想做的是优化整个事情并删除重复的表(并尽可能避免使用虚拟表)以将所有分数数据存储在一个具有以下列的表中:

userid, overall_score, overall_rank, trade_score, trade_rank, quest_score, quest_rank

我现在的问题是我如何才能以最好的方式做到这一点,还有其他方式如上所示(使用所有不同的表格)?欢迎使用 MYSQL 语句和/或 php 代码。 前段时间我尝试使用行号,但这不起作用a)因为它们不能在插入语句中使用,b)因为当过滤每个玩家(如上面示例中的'playerX')时,排名为1这是唯一返回的行。

【问题讨论】:

    标签: php mysql ranking


    【解决方案1】:

    好吧,您可以尝试使用以下配置创建表:

    id | name | score_overall | score_trade | score_quest | overall_rank | trade_rank | quest_rank
    

    如果这样做,您可以使用以下查询来填充表:

    SET @overall_rank:=-(SELECT COUNT(id) FROM users);
    SET @trade_rank:=@overall_rank;
    SET @quest_rank:=@overall_rank;
    
    SELECT *
    FROM users u
    INNER JOIN (SELECT id,
                       @overall_rank:=@overall_rank+1 AS overall_rank
                FROM users
                ORDER BY score_overall DESC) ovr
    ON u.id = ovr.id
    INNER JOIN (SELECT id,
                       @trade_rank:=@trade_rank+1 AS trade_rank
                FROM users
                ORDER BY score_trade DESC) tr
    ON u.id = tr.id
    INNER JOIN (SELECT id,
                       @quest_rank:=@quest_rank+1 AS quest_rank
                FROM users
                ORDER BY score_quest DESC) qr
    ON u.id = qr.id
    ORDER BY u.id ASC
    

    我已经为你准备了SQL-fiddle

    虽然我认为如果你开始获得大量记录,性能会很重要。

    解释一下:@*_rank 的东西是 SQL 变量。每增加一个新行,它们就会增加 1。

    【讨论】:

    • 性能并不重要,因为 cron 每十分钟运行一次。看到您的 sqlfiddle 后,我有一个问题:如果我想在 PHP 中使用它,如何设置变量。这是单独的查询吗?
    • 一共有4个查询。我确实希望您使用 mysqli 或 PDO(它们都支持多个查询)。如果使用 MySQL,请确保不要关闭两个查询之间的连接。
    • 是的,我已经注意到它类似于set_names。我试图在我的 phpmyadmin(phpmyadmin:4.0.5,mysql:5.5.24-0ubuntu0.12.04.1 -(Ubuntu))上执行查询,但我得到了负面排名。如果我在 SQLfiddle (http://sqlfiddle.com/#!2/6e200/1) 中使用它,它就像在你的 SQLfiddle 中一样工作。在我们的两个例子(你的和我的)中,我的排名都是负数。你有什么想法吗?
    • 尝试将所有@*-变量设置为0。
    • 谢谢,然后它工作:) [编辑:仅供参考:更新到 mysql:5.5.32 - 像 sqlfiddle,没有帮助。之前试过...]
    猜你喜欢
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-04
    相关资源
    最近更新 更多