Как рассчитать процентильный ранг для точечных итогов за разные промежутки времени?

На веб-сайте, основанном на PHP и CodeIgniter, user_id может получать репутацию для различных действий, в отличие от Stack Overflow. Каждый раз, когда репутация присуждается, в таблице MySQL создается новая запись с usersуказанием вознаграждения и значения этой группы точек (например, 10 репутации). В то же время обновляется поле в reputation_totalтаблице user_id.

Поскольку все это бессмысленно без системы отсчета, я хочу показать пользователям их процентный рейтинг среди всех пользователей. Для полной репутации это кажется достаточно простым. Скажем , мой 1138есть users. Просто подсчитайте количество пользователей в usersтаблице с reputation_totalменьшей, чем моя, подсчитайте общее количество пользователей и разделите, чтобы найти процент пользователей с более низкой репутацией, чем моя. Это будет процентный ранг пользователя 1138, верно? Легко!

Но я также показываю итоги репутаций за разные промежутки времени - например, заработанные за последние семь дней, которые включают в себя запрос таблицы репутации и суммирование всех моих очков, полученных за определенную дату. Я также хотел бы показать процентильный ранг для разных временных интервалов - например, я могу быть 11-м процентилем в целом, но 50-й процентиль в этом месяце и 97-й процентиль сегодня.

Кажется, мне придется пройти и найти итоговые значения репутации для всех пользователей за данный промежуток времени, а затем посмотреть, где я попадаю в эту группу, нет? Разве это не ужасно громоздко? Каков наилучший способ сделать это?

Большое спасибо.

php,mysql,math,codeigniter,

3

Ответов: 2


1 принят

Я могу придумать несколько вариантов от верхней части головы:

  1. Как вы уже упоминали, суммируйте очки репутации, полученные за время, и подсчитайте на них процентильные ряды.

  2. Отслеживайте обновления до репутации_total на ежедневной основе - так что у вас есть таблица с user_id, date, reputation_total.

  3. Добавьте несколько новых столбцов в таблицу пользователей (репутация_total, репутация_total_today, репутация_total_last30days и т. Д.) Для каждого временного диапазона. Вы также можете нормализовать это в отдельной таблице (репутация_трега), чтобы предотвратить добавление нового столбца для каждого промежутка времени, который вы хотите отслеживать.

Вариант №1 является самым простым, но, вероятно, он будет медленным, если у вас много строк в таблице транзакций вашей репутации - он не будет масштабироваться очень хорошо, особенно если вам нужно рассчитать их в реальном времени.

Вариант № 2 потребует большего времени на хранение (одна строка на пользователя в день), но, вероятно, будет значительно быстрее, чем напрямую запрашивать таблицу транзакций.

Вариант № 3 менее гибок, но, скорее всего, будет самым быстрым вариантом.

Оба варианта 2 и 3, вероятно, потребуют периодического процесса для расчета итогов на ежедневной основе, так что это тоже нужно учитывать.

Я не думаю, что какой-либо вариант обязательно является лучшим - все они связаны с различными компромиссами скорости / пространства / сложности / гибкости. То, что вы делаете, в конечном итоге будет зависеть от требований для вашего применения.


1

Я не понимаю, почему это слишком сложно. Как правило, все, что вам нужно, это добавить к предложению WHERE запрос, который ограничивает результаты, такие как:

WHERE DatePosted between @StartOfRange and @EndOfRange
PHP, MySQL, математика, CodeIgniter,
Похожие вопросы