Voici une solution alternative :ne stockez pas du tout les rangs ! :-)
Vous pouvez les calculer à la volée.
Exemple :
SELECT id, (@next_rank := IF(@score <> score, 1, 0)) nr,
(@score := score) score, (@r := IF(@next_rank = 1, @r + 1, @r)) rank
FROM rank, (SELECT @r := 0) dummy1
ORDER BY score DESC;
Résultat :
+------+----+-------+------+
| id | nr | score | rank |
+------+----+-------+------+
| 2 | 1 | 23 | 1 |
| 4 | 1 | 17 | 2 |
| 1 | 0 | 17 | 2 |
| 5 | 1 | 10 | 3 |
| 3 | 1 | 2 | 4 |
+------+----+-------+------+
nr
voici une colonne auxiliaire qui indique si nous devons attribuer le rang suivant ou non.
Vous pouvez envelopper cette requête dans un autre select
et effectuer une pagination, par exemple.
SELECT id, score, rank
FROM (SELECT id, (@next_rank := IF(@score <> score, 1, 0)) nr,
(@score := score) score, (@r := IF(@next_rank = 1, @r + 1, @r)) rank
FROM rank, (SELECT @r := 0) dummy1
ORDER BY score DESC) t
WHERE rank > 1 and rank < 3;
Résultat :
+------+-------+------+
| id | score | rank |
+------+-------+------+
| 4 | 17 | 2 |
| 1 | 17 | 2 |
+------+-------+------+
ATTENTION :depuis maintenant rank
est une colonne calculée, vous ne pouvez pas l'indexer et parcourir efficacement l'ensemble de données (c'est-à-dire "sélectionner les enregistrements avec des rangs de 3000 à 3010"). Mais c'est toujours bon pour "sélectionner les N premiers rangs" (à condition que vous mettiez un LIMIT
correspondant sur une requête)