Como calcular percentil para o total de pontos ao longo de diferentes períodos de tempo?
-
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.
Solução
Não consigo pensar em algumas opções em cima da minha cabeça aqui:
-
Como você mencionou, somam-se os pontos de reputação ganhos durante o intervalo de tempo e calcular o percentil fileiras com base nisso.
-
atualizações pista para reputation_total em uma base diária -. Por isso você tem uma tabela com user_id, data, reputation_total
-
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