remoto - Clasificar usuarios en mysql por sus puntos
mariadb create user grant all privileges (3)
Estoy tratando de clasificar a mis estudiantes por sus puntos que he calculado antes, pero el problema es que si los estudiantes tienen los mismos puntos, ambos deberían estar en el mismo rango.
El estudiante 1 tiene puntos completos El estudiante 2 tiene puntos completos
ambos deben ser clasificados como 1;
Aquí un ejemplo de mi base de datos
la consulta que estoy tratando de hacer es (solo para seleccionar, entonces puedo insertar los valores en mi columna)
SELECT a.points
count(b.points)+1 as rank
FROM examresults a left join examresults b on a.points>b.points
group by a.points;
Editar por ser más claro:
- Estudiante 1 puntos 80
- Estudiante 2 puntos 77.5
- Estudiante 3 puntos 77.5
- Estudiante 4 puntos 77
sus rangos deberían ser como
- Estudiante 1 Rango 1
- Estudiante 2 Rango 2
- Estudiante 3 Rango 2
- Estudiante 4 Rango 3
mi consulta actual devuelve valores como
Como falta el tercer rango. (porque el segundo rango tiene 2 valores)
Desea un rango real, que se calcula mediante la función de rank()
estándar ANSI rank()
. Puede implementar esto en MySQL usando esta lógica:
select er.*,
(select 1 + count(*)
from examresults er2
where er2.points > er.points
) as ranking
from exampleresults er;
Para tablas más grandes, puede hacer esto con variables, pero es bastante incómodo:
select er.*,
(@rank := if(@rn := @rn + 1 -- increment row number
if(@points = points, @rank, -- do not increment rank
if(@points := points, -- set @points
@rn, @rn -- otherwise use row number
)
)
)
) as ranking
from examresults er cross join
(select @rn := 0, @rank := 0, @points := -1) params
order by points desc;
Esta es solo una solución de la solución de Gordon que usa variables. La cuestión es que la función de rango no es la forma en que el rango debería funcionar. (el estudiante 4 debe ser el rango 4)
Demostración de SQL Fiddle Puede agregar más estudiantes para mejorar las pruebas.
select er.*,
(@rank := if(@points = points,
@rank,
if(@points := points,
@rank + 1,
@rank + 1
)
)
) as ranking
from students er cross join
(select @rank := 0, @points := -1) params
order by points desc;
SALIDA
| id | points | ranking |
|----|--------|---------|
| 1 | 80 | 1 |
| 2 | 78 | 2 |
| 3 | 78 | 2 |
| 4 | 77 | 3 |
| 5 | 66 | 4 |
| 6 | 66 | 4 |
| 7 | 66 | 4 |
| 8 | 15 | 5 |
esta consulta logra lo que quieres:
SELECT student_id , points, (select count(distinct(points))+1 as rank
from examresults internal
where internal.points > external.points order by points)
FROM examresults external
group by student_id