【问题标题】:Recalculating ranks after each item is voted on对每个项目进行投票后重新计算排名
【发布时间】:2012-01-15 00:20:42
【问题描述】:

我有一张允许用户投票的项目表。在这个表中,有一个 votes 列,保存该项目累积的票数,还有一个 rank 列,这是根据他们拥有的票数对所有项目进行排名(即大多数票获得排名 1,第二多获得排名 2,依此类推)

目前,我在每次投票后重新计算每个项目的排名。也就是说,当用户投票时,我在该项目的 votes 列中添加一个,然后使用以下查询更新每个排名:

SET @rank = 0
UPDATE items SET rank = @rank := @rank + 1 ORDER BY votes DESC

这在大多数情况下都有效,但不考虑投票关系。如果我有投票 [10, 4, 3, 0],我希望排名 [1, 2, 3, 4]。但是,如果我有投票 [10, 10, 3, 0],我想要排名 [1, 1, 3, 4]。这不会发生;我仍然获得排名[1, 2, 3, 4]

我怎样才能像上面描述的那样合并关系?

【问题讨论】:

    标签: mysql sql database


    【解决方案1】:

    我不会将排名保存在数据库中。您可以在显示结果的同时计算它。

    $rank = 1;
    $lastVotes = -1;
    $lastAdd = 0;
    
    $query = mysql_query("SELECT * FROM table WHERE * ORDER BY votes DESC", $link);
    while( $row = mysql_fetch_array( $query ) ) {
      // local variable with votes
      $votes = $row['votes'];
    
      // check if we have a tie
      if( $lastVotes == $votes ) {
        // don't change rank if there is a tie but inc $lastAdd
        $lastAdd += 1;
      } else {
        // there is no tie: save last votes, adjust $rank and reset $lastAdd
        $lastVotes = $votes;
        $rank += $lastAdd;
        $lastAdd = 1;
      }
    
      // $rank is your rank
    }
    

    【讨论】:

    • +1 表示“我不会将排名保存在数据库中”。当您将聚合值或计算值保存在另一列中时,它们不同步的机会比比皆是。但是,有一些案例,它们通常与性能有关。在这些情况下,触发器和/或单独的表可能是合适的。此类性能问题需要分析使用情况。
    【解决方案2】:

    这个不优雅的解决方案会返回你想要的:

    update ITEMS I1
       set rank =
             (select count(*)
                from ITEMS I2
               where I2.VOTES >= I1.VOTES)
             - (select count(*) - 1
                  from ITEMS I3
                 where I3.VOTES = I1.VOTES)
    

    【讨论】:

    • 这很好用,只是它似乎没有更新数据库中的排名数据;它只返回每一行的新排名。
    【解决方案3】:

    没有 mysql 实例可以尝试这个,但是像这样的东西怎么样:

        SELECT v.id, v.votes, r.rank
          FROM votes v
              ,(SELECT votes, @rownum = @rownum + 1 AS rank
                  FROM votes
                  GROUP BY votes
                  ORDER BY votes DESC
               ) r
          WHERE v.votes = r.votes
          ORDER BY rank
    

    找出不同的“投票”集合,对它们进行排序,给每个人一个数字,然后用它来将数字(排名)与每个投票相关联。

    【讨论】:

    • 哦,我应该补充一点,排名是一个计算值,我也绝对不会将它存储在数据库中。
    【解决方案4】:

    确实取决于表大小和更新频率,但是触发器呢? MySQL- Trigger updating ranking

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 1970-01-01
      相关资源
      最近更新 更多