Com a seguinte tabela MySQL:
+-----------------------------+
+ id INT UNSIGNED +
+ name VARCHAR(100) +
+-----------------------------+
Como posso selecionar uma única linha E sua posição entre as outras linhas da tabela, quando classificado por name ASC
. Portanto, se os dados da tabela forem assim, quando classificados por nome:
+-----------------------------+
+ id | name +
+-----------------------------+
+ 5 | Alpha +
+ 7 | Beta +
+ 3 | Delta +
+ ..... +
+ 1 | Zed +
+-----------------------------+
Como posso selecionar a Beta
linha obtendo a posição atual dessa linha? O conjunto de resultados que procuro seria algo assim:
+-----------------------------+
+ id | position | name +
+-----------------------------+
+ 7 | 2 | Beta +
+-----------------------------+
Posso fazer um SELECT * FROM tbl ORDER BY name ASC
procedimento simples e, em seguida, enumerar as linhas em PHP, mas parece um desperdício carregar um conjunto de resultados potencialmente grande apenas para uma única linha.
sql
mysql
analytic-functions
leepowers
fonte
fonte
Respostas:
Usa isto:
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 obter um valor de posição único. Isto:
SELECT t.id, (SELECT COUNT(*) FROM TABLE x WHERE x.name <= t.name) AS position, t.name FROM TABLE t WHERE t.name = 'Beta'
... dará aos laços o mesmo valor. IE: Se houver dois valores em segundo lugar, ambos terão uma posição 2 quando a primeira consulta dará uma posição 2 para um deles e 3 para o outro ...
fonte
position
, mas é perfeito.Esta é a única maneira que consigo pensar:
SELECT `id`, (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`, `name` FROM `table` WHERE `name` = 'Beta'
fonte
name <= 'Beta'
lugarposition
valores para empates.LIMIT 1
lá? Em caso de empate, você teria apenas uma linha com a última posição do empate.name
campo é exclusivo - então não há razão para tornar a consulta mais complexa. Se ele não puder - então vamos esperar suas expectativas de resultado para nomes empatados.Se a consulta for simples e o tamanho do conjunto de resultados retornado for potencialmente grande, você pode tentar dividi-lo em duas consultas.
A primeira consulta com um critério de filtragem restrito apenas para recuperar os dados dessa linha, e a segunda consulta usa
COUNT
aWHERE
cláusula com para calcular a posição.Por exemplo, no seu caso
Consulta 1:
SELECT * FROM tbl WHERE name = 'Beta'
Consulta 2:
SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'
Usamos essa abordagem em uma tabela com registro de 2M e é muito mais escalável do que a abordagem dos pôneis OMG.
fonte
As outras respostas parecem muito complicadas para mim.
Aqui está um exemplo fácil , digamos que você tenha uma tabela com colunas:
e você deseja classificar as IDs de usuário por pontos e obter a posição da linha (a "classificação" do usuário), então você usa:
SET @row_number = 0; SELECT (@row_number:=@row_number + 1) AS num, userid, points FROM ourtable ORDER BY points DESC
num
fornece a posição da linha (classificação).Se você tem MySQL 8.0+ então você pode querer usar ROW_NUMBER ()
fonte
A posição de uma linha na tabela representa quantas linhas são "melhores" do que a linha desejada.
Portanto, você deve contar essas linhas.
SELECIONE A CONTAGEM (*) + 1 DE
table
ONDEname
<'Beta'Em caso de empate, a posição mais alta é devolvida.
Se você adicionar outra linha com o mesmo nome de "Beta" após a linha "Beta" existente, a posição retornada ainda será 2, pois eles compartilham o mesmo lugar na classificação.
Espero que ajude pessoas que vão buscar algo semelhante no futuro, pois acredito que o dono da questão já resolveu o problema.
fonte
Estou com um problema muito parecido, por isso não vou fazer a mesma pergunta, mas vou compartilhar aqui o que eu fiz, tive que usar também um agrupar por e ordenar por AVG. Existem alunos, com assinaturas e socore, e eu tive que classificá-los (em outras palavras, eu primeiro calculei o AVG, depois ordenei em DESC e, finalmente, precisei adicionar a posição (classificação para mim). algo muito parecido com a melhor resposta aqui, com algumas pequenas mudanças que se ajustam ao meu problema):
Eu coloquei finalmente a
position
coluna (classificação para mim) no 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
fonte
Eu estava analisando a resposta aceita e parecia um pouco complicado, então aqui está a versão simplificada dela.
SELECT t,COUNT(*) AS position FROM t WHERE name <= 'search string' ORDER BY name
fonte
Tenho tipos semelhantes de problemas em que exijo classificação ( índice ) da mesa
order by votes desc
. O seguinte funciona bem para mim.Select *, ROW_NUMBER() OVER(ORDER BY votes DESC) as "rank" From "category_model" where ("model_type" = ? and "category_id" = ?)
fonte
pode ser o que você precisa é adicionar sintaxe
então use
SELECT * FROM tbl ORDER BY name ASC LIMIT 1
se você só precisa de uma linha ..
fonte