2011-10-09 133 views
0

我有一个包含用户和积分的数据库(实际上它是一个百分比,但这并不重要)。用户(S)与点的最高的数字是第一级,第二个第二级...使用积分计算排名

如果我这样做somethink这样我能得到一个$searchedUserID的排名:

SELECT `user_id`, `points` FROM `usertable` ORDER BY `points` DESC 
/** This function returns the rank of a user. The rank nr. 1 is the best. 
* It is possible that some users share a rank. 
* 
* @param int $searchedUserID the ID of the user whose rank you would like to 
*       know 
* 
* @return int rank 
*/ 
function getUserRank($searchedUserID) 
{ 
    $userArray = getAllUsersOrderedByPoints(); 
    $rank  = 0; 
    $lastPoints = -1; // Never happens 
    foreach ($userArray as $user) { 
     if ($user['point'] != $lastPoints) $rank++; 
     if ($user['user_id'] == $searchedUserID) break; 
    } 
    return $rank; 
} 

是不是有一种更直接的方式来获得(My)SQL? 如果不是的话:PHP部分可以改进吗?

(编辑:我可以存储由PHP直接在数据库中计算的排名......但是这将意味着我不得不做出相当多的更新。)

EDIT2:也许GROUP BY可以使用?喜欢的东西:

SELECT `user_id`, `points` FROM `usertable` GROUP BY `points` ORDER BY `points` DESC 

该查询的问题的可能性,我没有得到的搜索USER_ID。这将是必要发送第二查询:

SELECT `user_id` FROM `usertable` WHERE `points` = $pointsOfTheUser 
+1

一般来说,它比使用mySQL更快地对PHP进行排序。如果你在最后一个查询中使用或不使用'ORDER BY'对查询执行'EXPLAIN',你会明白我的意思。这是数据集变大时要考虑的事情。只是我的2cp。 –

+3

我喜欢'//不会发生'评论;) – sjngm

+0

@sjngm:这对了解最佳排名是否应该是重要的。如果我使用负排名,最高的数字是-1,返回的排名是0.但是,我不知道为什么有人应该使用负点;-) –

回答

0

你问:

是不是有一个更直接的方式与(我的)SQL得到这个?

是的。在SQL:2003中,可以使用DENSE_RANK()窗口函数。在MySQL中,你可以模拟这一点,如一些得分纪录(密集)排名仅仅是截然不同的更好的成绩的计数+ 1:组

SELECT u.user_id, 
      u.points, 
      1 + COUNT(DISTINCT others.points) AS `dense_rank` 
    FROM users u 
LEFT JOIN users others 
      ON u.points < others.points -- Which other users have more points? 
    WHERE user_id = ? 
GROUP BY 1, 2; 
0

也许内参加由和排序会做的招?

SELECT * FROM 
INNER JOIN 
    (
    SELECT user_id AS uid, max(points) AS score 
    FROM usertable GROUP BY user_id 
) 
AS ds ON usertable.user_id = ds.uid AND usertable.points = ds.score 
ORDER BY score DESC 

只是想在纸上(像素)..不会说给你名单,以便从最高点到最低的每用户一个唯一的记录...或者你希望有这些分类,你可以在排名中将一条领带作为单一的“地点”来澄清?