2010-07-07 10 views
9

Estoy tratando de resolver mi consulta y no puedo entenderlo. Agradecería que alguien me diera un puntero. Como un simple ejemplo de lo que estoy tratando de lograr, tengo estos registros en la base de datosDeclaración de actualización de MySQL para almacenar posiciones de clasificación

Score|Ranking 
------------- 
100 |0 
200 |0 
300 |0 

Y me gustaría que el campo de clasificación para contener 1,2,3 basado en quién tiene la puntuación más alta por lo que la resultado debe ser:

Score|Ranking 
------------- 
100 |3 
200 |2 
300 |1 

por el momento, estoy haciendo un bucle para el próximo para todos estos registros, pero teniendo en cuenta que, en realidad, que podría ser unos pocos miles - que podría tener para siempre! ¿Alguien tiene una idea sobre una consulta mágica que haría esto de una vez?

Respuesta

4

En MySQL, puede usar row_number.

Here's an example de utilizarlo en una SELECT:

select @rownum:[email protected]+1 ‘rank’, p.* 
from player p, (SELECT @rownum:=0) r 
order by score desc; 

Si INSERT INTO utilizando un SELECT como este, obtendrá su clasificación.

+0

+1: Normalmente diría que esto debería estar en una vista, pero las vistas de MySQL no permiten el uso variable. Hay una alternativa usando COUNT en una subselección para obtener el valor de clasificación que funcionaría en una vista que imagino ... –

+10

¿Dónde se actualizan los valores en la base de datos? – quantumSoup

4

Esto crea una declaración de actualización en línea que clasificará a sus jugadores incrementando por la variable @rc. Lo he usado muchas veces en casos muy similares, funciona bien y lo mantiene todo en el lado de DB.

SET @rc = 0; 
UPDATE players JOIN (SELECT @rc := @rc + 1 AS rank, id FROM players ORDER BY rank DESC) 
AS order USING(id) SET players.rank = order.rank; 

id se supone que es la clave principal para la tabla players.

16

Aquí está una manera de hacerlo:

SET @r=0; 
UPDATE table SET Ranking= @r:= (@r+1) ORDER BY Score DESC; 

/* use this if you just want to pull it from the db, but don't update anything */ 
SET @r=0; 
SELECT *, @r:= (@r+1) as Ranking FROM table ORDER BY Score DESC; 
+1

Consulte la versión de DOK: no requiere la instrucción SET, es completamente independiente. –

+2

Autónomo en el sentido de que está en una sola consulta, sí; pero eso es porque está configurando @rownum en la subconsulta SELECT. Lo cual creo que parece más desordenado. – quantumSoup

+0

La belleza está en el ojo del espectador, pero es menos probable que la capacidad de enviar una sola declaración tenga problemas –

0

les muestro mi forma de hacerlo [para las funciones SQL de actualización de intervalo]

seleccione:

set @currentRank = 0, 
    @lastRating = null, 
    @rowNumber = 1; 
select 
    *, 
    @currentRank := if(@lastRating = `score`, @currentRank, @rowNumber) `rank`, 
    @rowNumber := @rowNumber + if(@lastRating = `score`, 0, 1) `rowNumber`, 
    @lastRating := `score` 
from `table` 
order by `score` desc 

actualización:

set @currentRank = 0, 
    @lastRating = null, 
    @rowNumber = 1; 
update 
    `table` r 
    inner join (
     select 
      `primaryID`, 
      @currentRank := if(@lastRating = `score`, @currentRank, @rowNumber) `rank`, 
      @rowNumber := @rowNumber + if(@lastRating = `score`, 0, 1) `rowNumber`, 
      @lastRating := `score` 
     from `table` 
     order by `score` desc 
    ) var on 
     var.`primaryID` = r.`primaryID` 
set 
    r.`rank` = var.`rank` 

i no realizó ningún control de rendimiento en este, excepto para las pruebas que funciona

2
SET @r = 0; 
UPDATE players JOIN (SELECT @r := @r + 1 AS rank, id FROM players ORDER BY rank DESC) 
AS sorted USING(id) SET players.rank = sorted.rank; 
Cuestiones relacionadas