Con la siguiente tabla MySQL:
+-----------------------------+
+ id INT UNSIGNED +
+ name VARCHAR(100) +
+-----------------------------+
¿Cómo puedo seleccionar una sola fila Y su posición entre las otras filas de la tabla, cuando se ordena por name ASC
. Entonces, si los datos de la tabla se ven así, cuando se ordenan por nombre:
+-----------------------------+
+ id | name +
+-----------------------------+
+ 5 | Alpha +
+ 7 | Beta +
+ 3 | Delta +
+ ..... +
+ 1 | Zed +
+-----------------------------+
¿Cómo podría seleccionar la Beta
fila obteniendo la posición actual de esa fila? El conjunto de resultados que estoy buscando sería algo como esto:
+-----------------------------+
+ id | position | name +
+-----------------------------+
+ 7 | 2 | Beta +
+-----------------------------+
Puedo hacer un simple y SELECT * FROM tbl ORDER BY name ASC
luego enumerar las filas en PHP, pero parece un desperdicio cargar un conjunto de resultados potencialmente grande solo para una sola fila.
sql
mysql
analytic-functions
leepowers
fuente
fuente
Respuestas:
Utilizar esta:
SELECT x.id, x.position, x.name FROM (SELECT t.id, t.name, @rownum := @rownum + 1 AS position FROM TABLE t JOIN (SELECT @rownum := 0) r ORDER BY t.name) x WHERE x.name = 'Beta'
... para obtener un valor de posición único. Esta:
SELECT t.id, (SELECT COUNT(*) FROM TABLE x WHERE x.name <= t.name) AS position, t.name FROM TABLE t WHERE t.name = 'Beta'
... le dará a las corbatas el mismo valor. IE: Si hay dos valores en el segundo lugar, ambos tendrán una posición de 2 cuando la primera consulta dará una posición de 2 a uno de ellos y 3 a la otra ...
fuente
position
, pero es perfecto.Esta es la única forma en la que puedo pensar:
SELECT `id`, (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`, `name` FROM `table` WHERE `name` = 'Beta'
fuente
name <= 'Beta'
en su lugarposition
valores para los empates.LIMIT 1
allí? En caso de empate, obtendría solo una fila con la última posición del empate.name
campo sea único, entonces no hay razón para hacer la consulta más compleja. Si no puede, esperemos sus expectativas de resultados para nombres empatados.Si la consulta es simple y el tamaño del conjunto de resultados devuelto es potencialmente grande, entonces puede intentar dividirlo en dos consultas.
La primera consulta con un criterio de filtrado restringido solo para recuperar datos de esa fila, y la segunda consulta usa la cláusula
COUNT
withWHERE
para calcular la posición.Por ejemplo en tu caso
Consulta 1:
SELECT * FROM tbl WHERE name = 'Beta'
Consulta 2:
SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'
Usamos este enfoque en una tabla con un registro de 2M y esto es mucho más escalable que el enfoque de OMG Ponies.
fuente
Las otras respuestas me parecen demasiado complicadas.
Aquí viene un ejemplo sencillo , digamos que tiene una tabla con columnas:
y desea ordenar los ID de usuario por puntos y obtener la posición de la fila (la "clasificación" del usuario), luego usa:
SET @row_number = 0; SELECT (@row_number:=@row_number + 1) AS num, userid, points FROM ourtable ORDER BY points DESC
num
le da la posición de la fila (clasificación).Si tiene MySQL 8.0+, es posible que desee usar ROW_NUMBER ()
fuente
La posición de una fila en la tabla representa cuántas filas son "mejores" que la fila de destino.
Entonces, debes contar esas filas.
SELECCIONAR CONTADOR (*) + 1 DESDE
table
DONDEname
<'Beta'En caso de empate, se devuelve la posición más alta.
Si agrega otra fila con el mismo nombre de "Beta" después de la fila "Beta" existente, la posición devuelta seguirá siendo 2, ya que compartirían el mismo lugar en la clasificación.
Espero que esto ayude a las personas que buscarán algo similar en el futuro, ya que creo que el propietario de la pregunta ya resolvió su problema.
fuente
Tengo un problema muy, muy similar, por eso no haré la misma pregunta, pero compartiré aquí qué hice, tuve que usar también un grupo por y un pedido por AVG. Hay estudiantes, con firmas y socore, y tuve que clasificarlos (en otras palabras, primero calculé el AVG, luego los ordené en DESC, y finalmente necesitaba agregar la posición (rango para mí), así que lo hice algo muy similar a la mejor respuesta aquí, con pequeños cambios que se ajustan a mi problema):
Puse finalmente la
position
columna (rango para mí) en el SELECT externoSET @rank=0; SELECT @rank := @rank + 1 AS ranking, t.avg, t.name FROM(SELECT avg(students_signatures.score) as avg, students.name as name FROM alumnos_materia JOIN (SELECT @rownum := 0) r left JOIN students ON students.id=students_signatures.id_student GROUP BY students.name order by avg DESC) t
fuente
Estaba revisando la respuesta aceptada y parecía un poco complicado, así que aquí está la versión simplificada.
SELECT t,COUNT(*) AS position FROM t WHERE name <= 'search string' ORDER BY name
fuente
Tengo problemas similares en los que necesito el rango ( índice ) de la tabla
order by votes desc
. Lo siguiente funciona bien para mí.Select *, ROW_NUMBER() OVER(ORDER BY votes DESC) as "rank" From "category_model" where ("model_type" = ? and "category_id" = ?)
fuente
puede ser lo que necesita es agregar sintaxis
así que usa
SELECT * FROM tbl ORDER BY name ASC LIMIT 1
si solo necesitas una fila ...
fuente