我有一个包含字段 id、投票(针对每个用户)、评分的表格。
任务:根据对他和其他人的投票计算用户评分。也就是我每次更新字段投票需要重新计算字段评分。
这意味着有些人可以排在第三位。投票给他,他将获得第二名,反之亦然 - 从 2 到 3。(在评级领域)
如何解决这个问题呢?每次更新字段以计算用户对 php 的评分并在 mysql 中进行大量更新查询是非常昂贵的。
嗯,这取决于很多因素
如果所有答案都为“否” ,那么您当前的更新方法将可以正常工作。无论如何,只要确保您应用最佳编码和 MySQL 表实践即可。
假设您的大部分或全部答案都是“是”,那么我将建议以下内容:
INSERT
记录记录到您的表格中INSERT
,添加时间戳,如果不可能,则添加用户 ID,然后可能是 IP 地址/位置SELECT
可以计算选票并计算评分的语句。投票计数列表顶部的人将在SELECT
. 此外,您可以过滤每个主题、每天、每个用户,并且您还应该能够根据所需的结果确定音量。当然,所有这些都取决于您的系统将来如何扩展。这可能有点矫枉过正,但值得考虑。
如果您想在没有评级列的情况下通过选择获得评级,那么这就是方法。但是从性能的角度来看,我不能保证这将是您的最佳选择。它的工作方式是,如果两个用户的票数相同,他们将获得相同的评分,然后它将跳过下一个不同评分所需的数字:
set @rating:=0;
set @count:=1;
select id,
case when @votes<>votes then @rating:=@rating+@count
else @rating end as rating,
case when @votes=votes then @count:=@count+1
else @count:=1 end as count,
@votes:=votes as votes
from t1
order by votes desc
这为您提供了一个可以忽略的额外列,或者您可以将此选择包装到子查询中并具有:
select t2.id,t2.votes,t2.rating from (
select id,
case when @votes<>votes then @rating:=@rating+@count
else @rating end as rating,
case when @votes=votes then @count:=@count+1
else @count:=1 end as count,
@votes:=votes as votes
from t1
order by votes desc) as t2
但是sqlfiddle奇怪地给出了不一致的结果,所以你必须做一些测试。如果有人知道为什么会这样,我会很想知道原因。
如果您只想获得一个用户的评分,那么执行子查询选项并在where
后面使用 afrom
应该会给您想要的结果。sqlfiddle - 但同样,结果不一致,运行它几次,有时它给出的评级为 10,其他时间为 30。我认为在你的数据库中进行测试以查看会发生什么将是最好的。
我建议在查询数据时这样做。它会简单得多。按票数降序排列。
也许在查询数据时创建一个视图并使用该视图。
你可以尝试这样的事情:
SET @rank := 0
select id, count(*) as votes, @rank := @rank + 1
from users
group by id
order by votes desc
或者
SET @rank := 0
select id, votes, @rank := @rank + 1
from users
order by votes desc
不使用字段 id、votes 和 rating,而是将表更改为具有字段 id、rating_sum 和 rating_count。每次你有一个新的评级时,你都会像这样查询数据库:
"UPDATE `ratings` SET `rating_count` = `rating_count` + 1, `rating_sum` = `rating_sum`+ $user_rating WHERE `id` = $id"
现在评分只是平均值 -> rating_sum / rating_count。不需要有一个带有评级的字段。
此外,为了防止用户多次评分,您可以创建一个名为 rating_users 的表,该表将有两个外键 users.id 和 rating.id。主键将是(users.id,ratings.id)。因此,每次用户首先尝试评分时,您都会检查此表。
是的,聚合很昂贵。您可以每五分钟左右更新一次排名表并从那里查询。您现在可能已经进行的查询是这样的:
select id, count(*) as votes
from users
group by id
order by votes desc