2011-05-14 3 views
1

Le week-end prochain, nous aurons une compétition avec 3 qualifications une demi-finale et une finale. Seuls les 15 meilleurs participants pouvaient participer à la demi-finale. Seuls les meilleurs 6 s'affrontent en finale.mySQL Classement (et tirages)

dans les qualifications que vous obtenez un score de 0 à 100 pour chaque qualification

Je cherche à trouver un moyen de sélectionner les contesters pour la demi-finale. Cela devrait être fondée sur (rang de qualification1) * (rang de qualification2) * (rang de qualification3)

donc je besoin de quelque chose comme:

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 

mais bien sûr, ce n'est pas valide mySQL.

Outre ce problème si tho contesters ont le même score, ils devraient être inclus dans les deux demi-finales, même si cela dépasse le maximum de 15

Pour la finale, nous voudrions choisir le meilleur 6 des scores en demi-finale. Si 2 scores sont les mêmes que nous voudrions choisir les qualifications ..

Répondre

5

option 1: postgres d'utilisation, qui prennent en charge les fonctions de fenêtrage (à savoir RANK() et DENSE_RANK())

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

option 2: utiliser une auto-jointure: le rang d'un utilisateur ayant le score X est (1 + le nombre (*) d'utilisateurs ayant un score inférieur à X); cela est susceptible d'être assez lent

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 

option 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 

EDIT

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

Salut, Merci pour la réponse rapide. Option 1: Postreg est une option, je ne cours pas sur mon propre serveur .. Option 2: En effet lent, mais c'est d'accord. Malheureusement, je dois classer 3 scores, pas seulement un. J'ai donc besoin des classements séparés, est-ce possible? Option 3: identique à l'option 2 – Tieme

+0

oui, vous devrez utiliser la 3ème requête 3 fois et les joindre sur user_id, et utiliser des variables @rownum différentes. – peufeu

+0

bien, c'est un dur! J'essayais depuis un moment mais pas de succès jusqu'à maintenant, je travaille dessus! – Tieme