2015-12-13 37 views
2

目的:的MySQL(JDBC) - 排行榜排名基於列的值

  • 查找由 「viewedUserId」

確定給定用戶排名等級:

  • 體驗越高越好(降低)等級。
  • 如果兩個或兩個以上的用戶擁有相同的體驗,那麼首先獲得該體驗的人將獲得更好的排名。 (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); 
    } 
} 

關注:

  • 上面的代碼將工作,我打算怎麼了它來說,但性能是一個主要因素。使用上面的代碼並不理想,因爲我們的「分數」表格將包含數十萬行。

回答

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) 
+0

我必須從這些結果中選擇以獲得特定用戶的排名嗎? 如果我將以下內容添加到該查詢: 其中s.user_id = 9017 等級是1,這是不正確的。 – Wonderlus

+1

@Wonderlus。 。 。這實際上是一個非常不同的問題,請參閱編輯的回覆。 –

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子句來過濾單個用戶。

+0

謝謝。我確實看過那篇文章,但似乎沒有正確解釋關係。 – Wonderlus

+0

那麼你應該爲ORDER BY子句添加另一個語句,以便根據另一列進行排序。 – Randrian