Я бы использовал таблицу голосования, подобную этой:
create table votes(
item_id
,user_id
,vote_dtm
,vote
,primary key(item_id, user_id)
,foreign key(item_id) references item(item_id)
,foreign key(user_id) references users(user_id)
)Engine=InnoDB;
Использование составного ключа в таблице innodb сгруппирует данные вокруг элементов, что значительно ускоряет поиск голосов, связанных с элементом. Я добавил столбец vote_dtm
, в котором будет находиться отметка времени, когда пользователь проголосовал.
Тогда я бы создал одно или несколько представлений, используемых для отчетности.
create view votes_monthly as
select item_id
,year(vote_dtm) as year
,month(vote_dtm) as month
,sum(vote) as score
,count(*) as num_votes
from votes
group
by item_id
,year(vote_dtm)
,month(vote_dtm);
Если у вас начнутся проблемы с производительностью, вы можете заменить представление таблицей, содержащей предварительно вычисленные значения, даже не касаясь кода отчета.
Обратите внимание, что я использовал count(*)
и sum(vote)
. Счетчик (*) будет возвращать количество поданных голосов, тогда как сумма возвращает число положительных голосов. Однако, если вы изменили столбец vote
, чтобы использовать +1 для повышающих голосов и -1 для понижающих голосов, сумма (голосование) вернула бы счет, очень похожий на то, как рассчитываются голоса в стеке.