Como calcular percentil para o total de pontos ao longo de diferentes períodos de tempo?

StackOverflow https://stackoverflow.com/questions/1007146

  •  06-07-2019
  •  | 
  •  

Pergunta

Em um web site baseado em CodeIgniter PHP &, os usuários podem ganhar reputação de várias ações, não muito diferente de estouro de pilha. Cada reputação tempo é atribuído, uma nova entrada é criada em uma tabela MySQL com o user_id, ação que está sendo recompensado, eo valor desse monte de pontos (por exemplo, 10 reputação). Ao mesmo tempo, um campo em uma tabela users, reputation_total, é atualizado.

Uma vez que tudo isso é uma espécie de sentido sem um quadro de referência, quero mostrar aos usuários o percentil entre todos os usuários. Para a reputação total, o que parece bastante fácil. Vamos dizer que o meu user_id é 1138. Basta contar o número de usuários na tabela de users com um reputation_total menos do que a minha, contar o número total de usuários, e dividir para encontrar a percentagem de utilizadores com uma reputação mais baixa do que a minha. Isso vai ser usuário 1138 do percentil classificação, certo? Fácil!

Mas também estou exibir totais reputação ao longo de diferentes períodos de tempo -. Por exemplo, ganhos nos últimos sete dias, o que envolve consultando a tabela a reputação e somando todos os meus pontos ganhos desde uma determinada data. Eu também gostaria de mostrar percentil classificação para os diferentes intervalos de tempo -. Por exemplo, eu posso ser 11 percentil geral, mas percentil 50 deste mês e 97 percentil hoje.

Parece que eu teria que passar e encontrar os totais de reputação de todos os usuários para um determinado intervalo de tempo, e depois ver onde eu caio dentro desse grupo, não? É que não terrivelmente complicado? Qual é a melhor maneira de fazer isso?

Muito obrigado.

Foi útil?

Solução

Não consigo pensar em algumas opções em cima da minha cabeça aqui:

  1. Como você mencionou, somam-se os pontos de reputação ganhos durante o intervalo de tempo e calcular o percentil fileiras com base nisso.

  2. atualizações pista para reputation_total em uma base diária -. Por isso você tem uma tabela com user_id, data, reputation_total

  3. Adicione algumas novas colunas para a tabela de usuário (reputation_total, reputation_total_today, reputation_total_last30days, etc) para cada intervalo de tempo. Você também pode normalizar isso em uma tabela separada (reputation_totals) para impedi-lo de ter que adicionar uma nova coluna para cada intervalo de tempo que você deseja acompanhar.

Opção # 1 é o mais fácil, mas provavelmente vai ficar lento se você tiver lotes de linhas em sua tabela de transação reputação - não vai escalar muito bem, especialmente se você precisa calcular estes em tempo real

Opção # 2 vai exigir mais espaço de armazenamento ao longo do tempo (uma linha por usuário por dia), mas provavelmente seria significativamente mais rápido do que consultando a tabela da transação diretamente.

Opção # 3 é menos flexível, mas seria provavelmente a opção mais rápida.

Ambas as opções 2 e 3 provavelmente exigiria um processo de lote para calcular os totais em uma base diária, então isso é algo a considerar também.

Eu não acho que qualquer opção é necessariamente o melhor - todos eles envolvem diferentes trocas de velocidade / espaço de armazenamento / complexidade / flexibilidade. O que você faz vai depender dos requisitos para a sua aplicação, é claro.

Outras dicas

Eu não vejo porque isso seria demasiado excessivamente complexa. Geralmente tudo que você precisa é adicionar à sua cláusula WHERE uma consulta que limita os resultados como:

WHERE DatePosted between @StartOfRange and @EndOfRange
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top