MySQL(JDBC) - 基于列值的排行榜排名

时间:2015-12-13 12:18:51

标签: mysql jdbc system ranking

目标:

  • 查找“seenUserId”
  • 标识的给定用户的排名

排名:

  • 经验越高,等级越好(越低)。
  • 如果两个或更多用户具有相同的体验,那么首先获得该体验的人将获得更好的排名。 ( updated_at 列存储currentTimeMillis(bigint / long))
  • 排名不应该打平。 (没有用户应该能够拥有与另一个用户相同的等级)

问题:

  • 是否可以计算查询中的排名,这样我们就不必手动循环并比较每个存储用户的结果。 (理想情况下,我们希望返回1个排名结果)

代码:

public static int getRank(Connection connection, int viewedUserId) throws SQLException {
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        statement = connection.createStatement();
        resultSet = statement.executeQuery("SELECT user_id FROM scores ORDER BY experience DESC, updated_at ASC");
        int rank = 1;
        while(resultSet.next()) {
            int userId = resultSet.getInt("user_id");
            if(userId == viewedUserId)
                return rank;
            rank++;
        }
        throw new SQLException("Failed to find rank for user: " + viewedUserId);
    } finally {
        DatabaseUtils.close(statement, resultSet);
    }
}

关注:

  • 以上代码将按照我的意图行事,但性能是一个主要因素。使用上面的代码并不理想,因为我们的“得分”表将包含数十万行。

2 个答案:

答案 0 :(得分:1)

是的,您可以在查询中执行此操作。 MySQL中最简单的方法是使用变量:

SELECT s.user_id, (@rn := @rn + 1) as rank
FROM scores s CROSS JOIN
     (SELECT @rn := 0) params
ORDER BY s.experience DESC, s.updated_at ASC;

为此,几乎所有其他数据库都支持ANSI标准函数row_number()rank()。此外,如果您有大量数据,scores(experience, updated_at, user_id)上的索引对性能而言是最佳的。

编辑:

要获得特定用户排名,最简单的方法是使用不带变量的查询:

select count(*)
from scores s cross join
     scores su
where su.user_id = $user_id and
      (s.experience > su.experience or
       s.experience = su.experience and s.updated_at <= su.updated_at)

答案 1 :(得分:0)

看看这个问题:https://dba.stackexchange.com/questions/13703/get-the-rank-of-a-user-in-a-score-table

他们有一张这样的桌子:

Id  Name    Score
1   Ida     100
2   Boo     58
3   Lala    88
4   Bash    102
5   Assem   99

并添加排名:

SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( score
ORDER BY score DESC ) 
FROM scores )
) AS rank
FROM scores

导致

id name  score rank
1  Ida   100   2
2  Boo    58   5
3  Lala   88   4
4  Bash  102   1
5  Assem  99   3

您还可以添加WHERE子句来过滤单个用户。

相关问题