2011-05-14 46 views
1

下周末我们将举行一场半决赛和决赛的三项比赛。只有最好的15名参赛者才能参加半决赛。总决赛只有最佳6人参赛。mySQL排名(并提取)

的资格你从0到100的得分为每个资格

我期待找到一种方法来选择半决赛的参赛选手。这应该是基于(qualification1的等级)*(qualification2的等级)*(qualification3的排名)

,所以我需要的东西,如:

select id, name, ((.... as RANK_OF_SCORE_1) * (.. as RANK_OF_SCORE_2) * (... as  RANK_OF_SCORE_3)) as qualification_score from participants order by qualification_score desc limit 15 

当然,但这不是有效的MySQL。

此外,如果寿参赛选手具有相同的比分,他们应该都包含在半决赛即使这超过了最大的15

决赛这个问题,我们要选择最好的6的半决赛比分。如果分数是一样的,我们希望在资格选择..

回答

5

选项1:使用的Postgres,支持窗口函数(即RANK()和DENSE_RANK())

SELECT user_id, score, rank() over (order by score desc) from scores; 
Time : 0.0014 s 

选项2:使用自联接:具有分数X的用户的排名是(1+分数小于X的用户的计数(*));这很可能是相当缓慢

CREATE TABLE scores(user_id INT PRIMARY KEY, score INT, KEY(score)); 
INSERT INTO scores SELECT id, rand()*100 FROM serie LIMIT 1000; 

SELECT a.user_id, a.score, 1+count(b.user_id) AS rank 
    FROM scores a 
    LEFT JOIN scores b ON (b.score>a.score) 
    GROUP BY user_id ORDER BY rank; 

+---------+-------+------+ 
| user_id | score | rank | 
+---------+-------+------+ 
|  381 | 100 | 1 | 
|  777 | 100 | 1 | 
|  586 | 100 | 1 | 
|  907 | 100 | 1 | 
|  790 | 100 | 1 | 
|  253 | 99 | 6 | 
|  393 | 99 | 6 | 
|  429 | 99 | 6 | 
|  376 | 99 | 6 | 
|  857 | 99 | 6 | 
|  293 | 99 | 6 | 
|  156 | 99 | 6 | 
|  167 | 98 | 13 | 
|  594 | 98 | 13 | 
|  690 | 98 | 13 | 
|  510 | 98 | 13 | 
|  436 | 98 | 13 | 
|  671 | 98 | 13 | 

time 0.7s 

选项3:

SET @rownum = 0; 
SELECT a.user_id, a.score, b.r FROM 
scores a 
JOIN (
    SELECT score, min(r) AS r FROM (
     SELECT user_id, score, @rownum:[email protected]+1 AS r 
     FROM scores ORDER BY score DESC 
    ) foo GROUP BY score 
) b USING (score) 
ORDER BY r; 

time : 0.0014 s 

编辑

SET @rownum1 = 0; 
SET @rownum2 = 0; 
SET @rownum3 = 0; 

SELECT s.*, s1.r, s2.r, s3.r FROM 
scores s 
JOIN 
(
    SELECT score_1, min(r) AS r FROM (
     SELECT score_1, @rownum1:[email protected]+1 AS r 
     FROM scores ORDER BY score_1 DESC 
    ) foo GROUP BY score_1 
) s1 USING (score_1) JOIN (
    SELECT score_2, min(r) AS r FROM (
     SELECT score_2, @rownum2:[email protected]+1 AS r 
     FROM scores ORDER BY score_2 DESC 
    ) foo GROUP BY score_2 
) s2 USING (score_2) JOIN (
    SELECT score_3, min(r) AS r FROM (
     SELECT score_3, @rownum3:[email protected]+1 AS r 
     FROM scores ORDER BY score_3 DESC 
    ) foo GROUP BY score_3 
) s3 USING (score_3) 
ORDER BY s1.r * s2.r * s3.r; 
+0

嗨,感谢您的快速回复。 选项1:Postreg是一个选项,我没有在我自己的服务器上运行。选项2:确实很慢,但那没关系。不幸的是,我必须排名3分,而不只是一个。所以我需要单独的排名,这可能吗? 选项3:与选项2相同 – Tieme 2011-05-14 19:01:23

+0

是的,您需要使用第三个查询3次并在user_id上加入它们,并使用不同的@rownum变量。 – peufeu 2011-05-14 20:32:35

+0

好吧,这是一个很难!已经尝试了一段时间,但现在还没有成功,正在努力! – Tieme 2011-05-15 08:32:42