2014-02-24 76 views
5

林加入3个表呈现的表与用户最高分PHP MySQL的排行榜表

我的表

game_log:

---ID---user_ID---score---time--- 
| 1  52  567  10 | 
| 2  53  641  13 | 
| 3  52  465  8 | 
| 4  53  451  14 | 
--------------------------------- 

用户:

---ID---name---countyid--- 
| 52 Dave  1  | 
| 53 John  2  | 
    ------------------------ 

县:

---countyid---countyname--- 
    |  1 Orange wichit | 
    |  2 Orange clemts | 
    -------------------------- 

SQL:

SELECT * FROM game_log 
INNER JOIN users ON game_log.user_ID=users.ID 
INNER JOIN county ON users.countyid=county.countyid 
ORDER BY game_log.score DESC , game_log.time LIMIT 20"; 

上面的代码给了我这样的结果:

Rank---Name--------County------Score---Time 
1  John  Orange clemts 641  13 
2  Dave  Orange wichit 567  10 
3  John  Orange clemts 465  8 
4  Dave  Orange wichit 451  14 

我的问题是,我想高分表与得分最高的显示前20名用户,而不是20个最高分。

像这样:

Rank---Name--------County------Score---Time 
1  John  Orange clemts 641  13 
2  Dave  Orange wichit 567  10 

需要这方面的帮助索姆,不熟悉的连接表;-)

+0

加入一个子查询,为每个组选择最高分数。 – Mihai

+0

如果用户有2个相同分数的实例,并且该分数是他们的最高分,并且他们位于前20名,那么您希望为用户带回哪条记录?具有最低或最高时间值的那个?或者是其他东西? –

回答

2

此方法将显示前20位用户和每位用户的最高分数,如果他们有多个相同分数的实例,则会显示最早的一个(该用户和分数的最低时间值)信息。

SELECT * 
    FROM game_log gl 
INNER JOIN users u 
    ON gl.user_ID = u.ID 
INNER JOIN county c 
    ON u.countyid = c.countyid 
WHERE not exists (select 1 
      from game_log gl2 
     where gl2.user_id = gl.user_id 
      and gl2.score > gl.score) 
    and not exists (select 1 
      from game_log gl2 
     where gl2.user_id = gl.user_id 
      and gl2.time < gl.time 
      and gl2.score = gl.score) 
ORDER BY gl.score DESC, gl.time LIMIT 20; 

没有这样做,如果前20名相同的用户有同样的比分2+倍,他们将列出2+次,你将不会被使用LIMIT 20,因为同样拿回20人人将采取N行指出,20

SQL小提琴这里显示了与领带的数据:http://sqlfiddle.com/#!2/0ac931/5/0

+0

完美,这对我有帮助!正是我需要的! –

1

我会做到这一点与not exists方法来获取每个用户的最高得分。查询的其余部分是相同的:

SELECT * 
FROM game_log gl INNER JOIN 
    users u 
    ON gl.user_ID = u.ID INNER JOIN 
    county c 
    ON u.countyid = c.countyid 
WHERE not exists (select 1 
        from game_log gl2 
        where gl2.user_id = gl.user_id and gl2.score > gl.score 
       ) 
ORDER BY gl.score DESC, gl.time 
LIMIT 20; 

where子句说:“记住这行,如果没有其他行对同一用户拥有更高的分数。”

另一种方式做,这是与聚合的方法:

SELECT * 
FROM (select user_id, max(score) as maxscore 
     from game_log gl 
     group by user_id 
    ) gl INNER JOIN 
    users u 
    ON gl.user_ID = u.ID INNER JOIN 
    county c 
    ON u.countyid = c.countyid 
ORDER BY gl.maxscore DESC 
LIMIT 20; 

但这种方法损失大约time的信息。可以包括这一点,但它会使查询更加复杂。

2

GROUP BY应该做的工作。

SELECT users.ID, users.name, county.countyname, MAX(game_log.score) AS score, game_log.time 
FROM game_log 
INNER JOIN users ON game_log.user_ID = users.ID 
INNER JOIN county ON users.countyid = county.countyid 
GROUP BY game_log.user_ID 
ORDER BY game_log.score DESC, game_log.time 
LIMIT 20; 

试用SQL Fiddle