2012-10-21 52 views
2

我有一個表,包括每個球員已經玩過的每場比賽的記錄。我已經得到來自這個問題上回答一個不錯的開端:Ranking with millions of entries,和現在使用的這個查詢檢索每個玩家的最高得分和他們的排名:有效的方法來選擇一個固定範圍的高分給予只有一個用戶ID

SET @rank=0; 

SELECT user_id, score, rank FROM (
    SELECT *, @rank := @rank + 1 as rank 
    FROM high_scores 
    JOIN (
     SELECT user_id as user_id2, MAX(score) AS max_score   
     FROM high_scores 
     GROUP BY user_id2 
     ORDER BY max_score DESC) AS max_score_table     
    ON max_score = high_scores.score AND high_scores.user_id = user_id2) derived_table 
ORDER BY rank; 

再次,這給了我一個很好的有序每個玩家的最高分和列表;不過,我還希望能夠提供特定的user_id,並將結果過濾到此用戶的分數以及X分數的周圍較高和較低分數。

我想我需要執行的「derived_table」一SELECT ... WHEREuser id和使用返回行的'rank'過濾頂級SELECT聲明,但除了甚至不被接受的查詢('derived_table不存在'),我這樣做的方式需要我重新查詢derived_table兩次(對於大於和小於測試),這使得查詢效率甚至比它應該低。

如何過濾高分的完整列表並將其排列到單個user_id的條目和X數量的周邊條目?任何關於我試圖提出的代碼(或我現在擁有的代碼)的深入瞭解將不勝感激。

回答

0
SELECT ranks.rank, ranks.user_id, ranks.maxscore FROM (

    -- find the rank of each user by counting the number of 
    -- users who have a score greater than that user's highest 
    SELECT currentuser.user_id, 
      currentuser.maxscore, 
      IFNULL(COUNT(DISTINCT high_scores.user_id),0) rank 
    FROM  high_scores JOIN (
    -- current user's highest score 
    SELECT user_id, MAX(score) maxscore FROM high_scores GROUP BY user_id 
) currentuser ON high_scores.score > currentuser.maxscore 
    GROUP BY currentuser.user_id 

) ranks JOIN (

    -- find the rank of the user we want similarly 
    SELECT IFNULL(COUNT(DISTINCT user_id),0) rank 
    FROM high_scores JOIN (
    -- our user's highest score 
    SELECT MAX(score) maxscore FROM high_scores WHERE user_id = ? 
) userscore ON high_scores.score > userscore.maxscore 

-- filter for only those who are within given range from our user's rank 
) userrank ON ranks.rank BETWEEN userrank.rank - ? AND userrank.rank + ? 

-- sort the results 
ORDER BY ranks.rank 
+0

感謝您的快速和徹底的答覆,eggyal。我花了一些時間試圖實現它,但似乎'@r:= IF(得分<=> @l,@r,@c)rank'返回一個「BLOB」而不是一個數字,儘管事實如此我會認爲在第一行它會返回NULL或'@ c'(它正確地返回一個數字而不是一個字符串)。除了在@第一次迭代之後將@ b指定給其返回的BLOB值之外,我不確定在哪裏有非數字進入。這個問題對你來說似乎很熟悉嗎? –

+0

@JohnnyCage:您可以明確地將結果轉換爲帶有@r:= CAST(IF(得分<=> @ 1,@r,@c)已簽名)rank的整數。 – eggyal

+0

再次感謝!我有另一個給你 - 我確實看到查詢命令的結果由'rows.rank',它確實輸出每個用戶的最高分,但查詢的哪一部分實際上排序列表的最高分? 'userrank'子查詢返回的排名似乎是準確的,但高分的完整列表似乎沒有按特定順序排列。我的第一個直覺是在'ranking'子查詢中添加'ORDER BY maxscore DESC',但是所有這些都是在排序結果重新排序之前排序錯誤排列的分數列表。 –

相關問題