2011-01-30 179 views
1

我在MySQL中有一個表讓我們只是說,例如它有兩個字段用戶名,遊戲名稱和分數。 我要計算用戶的排名爲indivudal遊戲的名字,所以我可以做查詢在PHP/MySQL中計算排名

SELECT * FROM scores WHERE `GameName` = 'Snake' ORDER BY `Score` DESC 

得到所有用戶的列表中的最高到最低的順序並指定一個數字給每個用戶。

但是有沒有一種更簡單的方法來獲得個人用戶的排名,而不是選擇整個表,因爲這似乎不太有效。

感謝

+0

我的想法是,如果你能做到這一點在MySQL中,這將是通過使用臨時表,子查詢,和/或計算行數與排名別名。訣竅是讓MySQL填充臨時表/子查詢,然後讓您只選擇一個結果(單個玩家的最高等級)。那將是我不知道如何去做的,沒有反覆試驗和測試。請參閱:http://jimlife.wordpress.com/2008/09/09/displaying-row-number-rownum-in-mysql/ – 2011-01-30 20:46:47

+0

我確實瞭解你,你正在尋找一個用戶的總體最高分等級球員,而不是該球員的最高分數,對嗎? – 2011-01-30 20:57:04

回答

4

如果你想要整體排名,你不得不排序整個表。簡而言之,如果不知道表中的其他職位,就無法知道某人的排名。這就是說,如果你擔心性能,這裏有一個相當簡單的解決方案 - 緩存你的排名查詢的結果(可能是另一個MySQL表!),然後查詢你的所有閱讀。當有人發佈新分數時,請重新計算您的臨時表。您可以定期清除特定排名下的所有記錄(比如,排名低於100的任何人都會從分數表中刪除),以便快速實現重新計算,因爲沒有人會在被較高分數擊倒後爬上排名。

# Create your overall leaderboards once 
create table leaderboards (rank integer primary key, score_id integer, game varchar(65), user_id integer, index game_user_id_idx (game, user_id)) 


# To refresh your leaderboard, we'll query the ranks for the game into a temporary table, flush old records from scores, then copy 
# the new ranked table into your leaderboards table. 
# We'll use MySQL's CREATE TABLE...SELECT syntax to select our resultset into it directly upon creation. 
create temporary table tmp_leaderboard (rank integer primary key auto_increment, score_id integer, game varchar(65), user_id integer) 
    select ID, GameName, UserID, from scores where GameName = '$game' order by score desc; 

# Remove old rankings from the overall leaderboards, then copy the results of the temp table into it. 
delete from leaderboards where game = '$game'; 
insert into leaderboards (rank, score_id, game, user_id) 
    select rank, score_id, game, user_id from tmp_leaderboard; 

# And then clean up the lower scores from the Scores table 
delete from scores join tmp_leaderboard on scores.id = tmp_leaderboard.score_id, scores.GameName = tmp_leaderboard.game where tmp_leaderboard.rank < 100; 

# And we're done with our temp table 
drop table tmp_leaderboard; 

然後,每當你想讀的遊戲排名:

select rank from leaderboards where game = '$game' and user_id = '$user_id'; 
1

從用戶表中獲得用戶ID,並用它在查詢


SELECT * FROM scores WHERE `GameName` = 'Snake' 
and `youruseridfield` = '$useridvalue' 
ORDER BY `Score` DESC 
+0

確保`$ useridvalue`已被轉義。 – zneak 2011-01-30 20:29:46

+0

是的,這是非常必要的 – 2011-01-30 20:31:29

+0

你不能在WHERE語句之前使用ORDER – Nazariy 2011-01-30 20:32:15

1

SELECT * FROM scores WHERE 'GameName' = 'Snake' && userID = '$userID' ORDER BY 'Score' DESC

0

您應該添加索引GameName和得分。 (並且在插入query => mysql_real_escape_string之前不要忘記跳過GameName)。 @Bryan:不應該是「AND」而不是「& &」?

1

是有趣的,看看是否有一種方式來獲得MySQL中的排名,但這裏是你如何能做到它在PHP:

function getRank($user, $game, $limit=50) { 
    $sql = " 
SELECT @rank:[email protected]+1 AS Rank, User, GameName 
FROM scores, (SELECT @rank:=1) AS i 
WHERE `GameName` = '$game' 
ORDER BY `Score` DESC 
LIMIT 0, $limit 
"; 

    $result = mysql_query($sql); 

    while ($row = mysql_fetch_assoc($result)) { 
     if ($row['User'] == $user) { 
      return $row['Rank']; 
     } 
    } 

    return -1; 
} 

請注意,我把限制在那裏,否則你不會得到30個結果回來。如果玩家沒有排名,它會返回-1。

1

不能從閱讀了大量的表中的數據逃脫 - 但你並不需要一路長途回你處理腳本:大概

SELECT COUNT(*) 
FROM scores 
WHERE `GameName` = 'Snake' 
AND user=$some_user; 

(因爲你想讓第一個人的等級爲'1'而不是'0',則增加結果)。

但是,如果您需要頻繁運行查詢,則值得維護排序結果的物化視圖。

1

我的一個查詢的解決方案:

select @rank:[email protected]+1 AS Rank,L1.* from 
    (select @rank:=0) as L2, 
    (select i.*,count(*) as sum 
     FROM 
     transactions t 
     LEFT JOIN companies c on (c.id = t.company_id) 
     LEFT JOIN company_industries ci on (c.id = ci.company_id) 
     LEFT JOIN industries i on (ci.industry_id = i.id) 
     GROUP by i.name 
     ORDER BY sum desc) as L1;