Uma opção é usar uma variável de classificação, como a seguinte:
SELECT first_name,
age,
gender,
@curRank := @curRank + 1 AS rank
FROM person p, (SELECT @curRank := 0) r
ORDER BY age;
A (SELECT @curRank := 0)
peça permite a inicialização da variável sem a necessidade de um SET
comando separado .
Caso de teste:
CREATE TABLE person (id int, first_name varchar(20), age int, gender char(1));
INSERT INTO person VALUES (1, 'Bob', 25, 'M');
INSERT INTO person VALUES (2, 'Jane', 20, 'F');
INSERT INTO person VALUES (3, 'Jack', 30, 'M');
INSERT INTO person VALUES (4, 'Bill', 32, 'M');
INSERT INTO person VALUES (5, 'Nick', 22, 'M');
INSERT INTO person VALUES (6, 'Kathy', 18, 'F');
INSERT INTO person VALUES (7, 'Steve', 36, 'M');
INSERT INTO person VALUES (8, 'Anne', 25, 'F');
Resultado:
+------------+------+--------+------+
| first_name | age | gender | rank |
+------------+------+--------+------+
| Kathy | 18 | F | 1 |
| Jane | 20 | F | 2 |
| Nick | 22 | M | 3 |
| Bob | 25 | M | 4 |
| Anne | 25 | F | 5 |
| Jack | 30 | M | 6 |
| Bill | 32 | M | 7 |
| Steve | 36 | M | 8 |
+------------+------+--------+------+
8 rows in set (0.02 sec)
partition by gender
parte da função analítica (que "números" o valor de classificação por sexo não para o resultado global)Aqui está uma solução genérica que atribui uma classificação densa sobre a partição às linhas. Ele usa variáveis de usuário:
Observe que as atribuições de variáveis são colocadas dentro da
CASE
expressão. Isso (em teoria) cuida da ordem da questão da avaliação. oIS NOT NULL
é adicionado para lidar com tipo de dados conversão e problemas de curto-circuito.PS: pode ser facilmente convertido em número de linha sobre partição, removendo todas as condições que verificam o empate.
Demonstração no db <> fiddle
fonte
ELSE @rank_count := @rank_count + 1
ORDER BY gender, age DESC
?Embora a resposta mais votada seja classificada, ela não particiona, você pode fazer uma junção automática para particionar tudo também:
Caso de Uso
Resposta :
fonte
Uma emenda da versão de Daniel para calcular o percentil junto com a classificação. Além disso, duas pessoas com as mesmas notas receberão a mesma classificação.
Resultados da consulta para dados de amostra -
fonte
Combinação das respostas de Daniel e Salman. No entanto, a classificação não dará como continua a sequência com os empates. Em vez disso, pula a classificação para a próxima. Portanto, o máximo sempre alcança a contagem de linhas.
Esquema e caso de teste:
Resultado:
fonte
A partir do MySQL 8, você pode finalmente usar as funções de janela também no MySQL: https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
Sua consulta pode ser escrita exatamente da mesma maneira:
fonte
@ Sam, seu ponto de vista é excelente em termos de conceito, mas acho que você não entendeu o que os documentos do MySQL estão dizendo na página referenciada - ou entendi errado :-) - e eu só queria adicionar isso para que, se alguém se sentir desconfortável com o @ A resposta de Daniel será mais tranqüila ou, pelo menos, um pouco mais profunda.
Você vê que o
"@curRank := @curRank + 1 AS rank"
interiorSELECT
não é "uma declaração", é uma parte "atômica" da declaração, portanto deve ser seguro.O documento que você faz referência mostra exemplos em que a mesma variável definida pelo usuário em 2 partes (atômicas) da instrução, por exemplo,
"SELECT @curRank, @curRank := @curRank + 1 AS rank"
.Pode-se argumentar que
@curRank
é usado duas vezes na resposta de @ Daniel: (1)"@curRank := @curRank + 1 AS rank"
oe (2) o"(SELECT @curRank := 0) r"
mas, já que o segundo uso faz parte doFROM
cláusula, tenho certeza de que é garantido que ele seja avaliado primeiro; essencialmente fazendo dela uma segunda e anterior declaração.De fato, na mesma página de documentos do MySQL que você referenciou, você verá a mesma solução nos comentários - pode ser de onde o @Daniel conseguiu; Sim, eu sei que são os comentários, mas são comentários na página oficial de documentos e isso tem algum peso.
fonte
A solução mais direta para determinar a classificação de um determinado valor é contar o número de valores antes dele. Suponha que tenhamos os seguintes valores:
30
valores são considerados 3º40
valores são considerados 6 (classificação) ou 4 (classificação densa)Agora, de volta à pergunta original. Aqui estão alguns dados de amostra que são classificados conforme descrito em OP (classificações esperadas são adicionadas à direita):
Para calcular
RANK() OVER (PARTITION BY Gender ORDER BY Age)
para Sarah , você pode usar esta consulta:Para calcular
RANK() OVER (PARTITION BY Gender ORDER BY Age)
para Todos linhas que você pode usar essa consulta:E aqui está o resultado (os valores agregados são adicionados à direita):
fonte
Se você deseja classificar apenas uma pessoa, pode fazer o seguinte:
Essa classificação corresponde à função RANK da Oracle (onde, se você tem pessoas com a mesma idade, elas obtêm a mesma classificação, e a classificação depois disso é não consecutiva).
É um pouco mais rápido do que usar uma das soluções acima em uma subconsulta e selecionar uma delas para obter a classificação de uma pessoa.
Isso pode ser usado para classificar todos, mas é mais lento que as soluções acima.
fonte
Person
tabela aumenta. É O (n ^ 2) vs O (n) mais lento.Para evitar o " porém " na resposta de Erandac em combinação com as respostas de Daniel e Salman, pode-se usar uma das seguintes "soluções alternativas de partição"
A classificação da partição na 3ª variante neste trecho de código retornará números de classificação contínuos. isso levará a uma estrutura de dados semelhante ao
rank() over partition by
resultado. Como um exemplo, veja abaixo. Em particular, o partitionSequence sempre começará com 1 para cada novo partitionRank , usando este método:fonte
fonte