Declaração de seleção do MySQL – Como calcular o ranking atual

Eu tenho uma tabela chamada user_rankings onde os votos ( voted ) são armazenados para cada usuário. Quero exibir o ranking atual dos usuários (esta semana) que depende da quantidade de votos que o usuário obteve.

exemplo para esclarecer:

  • RANK-NR, USERNAME, VOTED,
  • 1, nome1, 18 vezes
  • 2, nome1, 16 vezes
  • (meu ranking aqui), meu nome, 13 vezes

Neste exemplo, meu ranking deve ser 3. Se eu tivesse 17 votos, eu seria o número 2. Se houvesse cinco usuários acima de mim, eu seria o número 8. Eu acho que você adquire o ponto.

Agora eu posso exibir o número do ranking facilmente com um $i incrementado em PHP. Mas eu só quero mostrar uma lista limitada a dez usuários (uma lista de dez melhores) e diretamente depois da minha sorting atual, se eu não estiver naquela lista de dez melhores. Então, eu só estou me perguntando como obter meu número de ranking exato usando o MySQL. Estou assumindo que tem centenas de usuários nesta lista com uma quantidade diferente de votos.

Esta é a minha declaração no momento:

 SELECT `voted` FROM `users_ranking` WHERE `uid`='".$_SESSION['uid']."' AND WEEKOFYEAR(`date`)=WEEKOFYEAR(NOW()) LIMIT 1 

Não posso lhe dar o código exato, mas acho que o seguinte pode dar-lhe alguma ideia

selecione ‘RANK-NR’, ‘USERNAME’, ‘VOTED’ (selecione ‘RANK-NR’, ‘USERNAME’, ‘VOTED’, rank () over (ordem por ‘votado’ desc) como rank de users_ranking onde uid = ”. $ _ SESSION [‘uid’]. “‘E WEEKOFYEAR ( date ) = WEEKOFYEAR (NOW ())) como abc onde rank <11

Eu acho que rank () over (order by <>) deve funcionar

Acabei de descobrir que esta solução funciona:

 SELECT * FROM ( SELECT @ranking:= @ranking + 1 rank, a.`uid` FROM `users_ranking` a, (SELECT @ranking := 0) b ORDER BY a.`votes` DESC ) s WHERE `uid`='".$_SESSION['uid']."' AND WEEKOFYEAR(`date`)=WEEKOFYEAR(NOW()) LIMIT 1 

OK, exemplo para acompanhar o meu comentário. O que você costuma trabalhar, mas não há nada para forçar o MySQL a fazer o tipo antes de aplicar o ranking.

Como tal, usando um nível extra de sub-consulta, você daria isso (não testado). A sub-consulta interna está obtendo todos os ID de usuário para a semana relevante na ordem correta, enquanto a próxima consulta secundária externa aplica o ranking a este conjunto de resultados ordenados. A consulta externa apenas obtém a única linha retornada que você precisa.

 SELECT c.rank, c.uid FROM ( SELECT @ranking:= @ranking + 1 rank, a.uid FROM ( SELECT uid, votes FROM `users_ranking` WHERE WEEKOFYEAR(`date`) = WEEKOFYEAR(NOW()) ORDER BY votes DESC ) a, (SELECT @ranking := 0) b ) c WHERE c.uid = '".$_SESSION['uid']."' LIMIT 1 

Outra possibilidade de evitar a sub-consulta e também evitar a necessidade de uma variável é fazer uma associação. Este é (mis) usando TENDO para diminuir o resultado para a única linha em que você está interessado. O lado oposto desta solução é que se vários usuários tiverem a mesma pontuação, cada um deles receberá o mesmo ranking.

 SELECT b.uid, COUNT(a.uid) FROM users_ranking a LEFT OUTER JOIN users_ranking b ON WEEKOFYEAR(a.`date`) = WEEKOFYEAR(b.`date`) AND a.votes >= b.votes GROUP BY b.uid HAVING b.uid = '".$_SESSION['uid']."' 

EDITAR

Para dar os 10 melhores rankings: –

 SELECT b.uid, COUNT(a.uid) AS rank FROM users_ranking a LEFT OUTER JOIN users_ranking b ON WEEKOFYEAR(a.`date`) = WEEKOFYEAR(b.`date`) AND a.votes >= b.votes GROUP BY b.uid ORDER BY rank LIMIT 10 

Embora neste caso, talvez seja mais rápido usar uma sub-consulta. Você poderia então colocar a cláusula LIMIT na sub-consulta com ORDER BY, portanto, só precisaria usar as variables ​​para adicionar uma sorting a 10 linhas.

Não tenho certeza de como combinar isso com a consulta para um único usuário, principalmente porque não tenho certeza de como deseja juntar os 2 resultados juntos.