PHP函数显示从最高得分到用户时间戳的排名


PHP function to display rank from highest score with timestamp of the user

我真的需要帮助创建一个函数,从用户的最高得分计算排名。我在这里看到了很多如何查询MYSQL的例子,但我没有足够的PHP知识来创建函数。

我有一张桌子:

  PRIMARY
  blogs_id  users_id  blogs_score  blogs_rate_time
      1         23        1872     2015-09-09 05:21:51
      2         23        2146     2015-09-10 07:31:54
      3         23        2146     2015-09-10 07:32:26
      4         23        2852     2015-09-10 04:42:15 <-- same score but date older
      5         51        1793     2015-09-11 08:15:55
      6         88        2852     2015-09-11 09:33:18 <-- same score but date newer

我需要一个PHP函数来显示特定用户在其个人资料中的排名。例如,在用户id为23的用户配置文件页面中显示"2个位置",对于id为88的用户显示"1个位置"等。

我添加了列blogs_rate_time以防止并列。

如何为此创建函数?

  function blogsRate($user_id) {
      global $db;
      sql ="
          WHAT IS THE OPTIMIZED QUERY FOR THAT?
      ";
      $rank_query = $db->query($sql);
      HERE SUPPOSE TO BE foreach I guess?
      return ?;
  }

我正在使用smarty来显示结果:

 $smarty->assign('rank_place', $users->blogsRate($userID));

请帮我创建工作函数来解决这个问题。我非常感谢完整的函数,而不仅仅是mysql查询或函数的一部分。我是新手

提前感谢!

您可以按blogs_score和blogs_rate_time对查询进行排序,并相应地对行进行编号以获得费率。我看不到您的表名,所以我将其称为Ranks,查询如下所示。

Set @rowNumber = 0;
Select user_id, (@rowNumber := @rowNumber + 1) As Rank From Ranks 
Order By blogs_score Desc, blogs_rate_time Asc;

那么你的函数应该如下所示。

  function blogsRate($user_id) {
      global $db;
      sql ="Set @rowNumber = 0; 
      Select user_id, (@rowNumber := @rowNumber + 1) As Rank From Ranks 
      Order By blogs_score Desc, blogs_rate_time Asc;";
      $rank_query = $db->query($sql);
      while ($row = $rank_query->fetch_assoc()) {
        if ($row['user_id'] == $user_id) {
            return $row['Rank'];
        }
      }
      return null; // Or something else that you can capture for not found
  }

然而,这需要检索和迭代所有数据,因此在资源使用方面非常昂贵。为了解决这个问题,我们可以在数据库中运行搜索,只得到相关的结果。为了实现这一点,首先我们将生成排名的查询放在子查询中,并在该子查询中进行搜索,如下所示。

Set @rowNumber = 0;
Select * From (
  Select user_id, (@rowNumber := @rowNumber + 1) As Rank From Ranks 
  Order By blogs_score Desc, blogs_rate_time Asc
) T Where user_id = $user_id Limit 1;

Limit 1将只选择第一个结果,这应该是该user_id的最佳排名,因为我看到一个用户可能有多个排名。为了只为每个用户获得最佳排名,我们需要添加另一个子查询,该子查询只提供最佳分数和时间。

Select * From (
  Select user_id, (@rowNumber := @rowNumber + 1) As Rank
  From (
    Select user_id, MAX(blogs_score) blogs_score, 
      MAX(blogs_rate_time) blogs_rate_time
    From Ranks
    Group By user_id
  ) G
  Order By blogs_score Desc, blogs_rate_time Desc
) T Where user_id = $user_id;

你的功能应该像这个

  function blogsRate($user_id) {
      global $db;
      sql ="Set @rowNumber = 0;
      Select * From (
        Select user_id, (@rowNumber := @rowNumber + 1) As Rank
        From (
          Select user_id, MAX(blogs_score) blogs_score, 
            MAX(blogs_rate_time) blogs_rate_time
          From Ranks
          Group By user_id
        ) G
        Order By blogs_score Desc, blogs_rate_time Desc
      ) T Where user_id = $user_id";
      $rank_query = $db->query($sql);
      if ($rank_query->num_rows > 0) {
          $row = $rank_query->fetch_assoc();
          return $row['Rank']; 
      }
      else return null;
  }

SQL Fiddle:http://sqlfiddle.com/#!9/149023/11

$sql = '
    SET @rank=0;
    SELECT * 
    FROM (
        SELECT @rank:=@rank+1 AS rank, blogs_id, users_id, blogs_score, blogs_rate_time
        FROM YOUR_TABLE_NAME
        ORDER BY blogs_score DESC,  blogs_rate_time ASC
    ) AS sub_query_table
    WHERE users_id = ' . $user_id;

这应该奏效。它会给你一个唯一的结果,当然,除非你有多个user_id。MySQL在数据库排序方面比PHP快。

我不知道你的$db是什么,但我想它会返回一个数组,这样你就可以用之类的东西来获取值

返回$rank_query[0]。