如何在数据库中对产品评级进行建模?

Moh*_*mad 19 mysql database-design rating-system

在数据库中存储产品评级的最佳方法是什么?我记得以下两个(简化,并假设一个MySQL数据库)场景:

在products表中创建两列,分别存储所有投票的数量和总和.使用列可以在运行时或使用查询获得平均值.

这种方法意味着我只需要访问一个表,简化了一些事情.

通过创建另一个表来存储评级来规范化数据.

这会将评级数据隔离到一个单独的表中,而产品表则提供有关可用产品的数据.虽然它需要加入或单独查询评级.

哪种方法最好,规范化或非规范化?

Ale*_*lec 33

强烈建议使用不同的评级表来保持动态.不要担心数百(或数千或数万)的条目,这些都是数据库的花生.

建议:

产品
- id
- 名称
- 等

table products_ratings
- id
- productId
- rating
- date(如果需要)
- ip(如果需要,例如防止双重评级)
- 等

检索产品的所有评级1234:

SELECT pr.rating
FROM products_ratings pr
INNER JOIN products p
  ON pr.productId = p.id
  AND p.id = 1234
Run Code Online (Sandbox Code Playgroud)

产品的平均评级1234:

SELECT AVG(pr.rating) AS rating_average -- or ROUND(AVG(pr.rating))
FROM products_ratings pr
INNER JOIN products p
  ON pr.productId = p.id
  AND p.id = 1234";
Run Code Online (Sandbox Code Playgroud)

获得产品列表及其平均评分同样容易:

SELECT
  p.id, p.name, p.etc,
  AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN products_ratings pr
  ON pr.productId = p.id
WHERE p.id > 10 AND p.id < 20 -- or whatever
Run Code Online (Sandbox Code Playgroud)

  • @Mel:你_could_创建像Tom建议的另一个表.但是,添加评级,或添加评级和一些文本是非常相似的事情.在这种情况下,我会将它们组合在一个表中,以防止在路上出现冗余,并且因为将它们拆分起来并没有真正的优势.空列不占用空间或影响速度; 它完全没问题(只要它们具有适当的功能,这就是这种情况).这与在产品表中添加"注释"列相同,但不是每个产品都可能有或需要注释. (3认同)

Dav*_*vid 6

我知道我的答案并不是您真正要求的,但您可能希望有机会促进您的系统的新产品几乎永远无法击败旧产品。假设您将获得评分为 99% 的产品。如果按照评分最高的产品来排序,新产品很难获得高分。


Sal*_*vaf 5

除非您绝对需要,否则不要存储每个评级的记录。这种情况的一个例子是心理实验,该实验倾向于分析评估者本身的特定属性。嗯是的!您必须同样疯狂才能将每个费率存储在单独的记录中。

现在,来到解决方案,在您的产品表中再添加两列:AverageRatingRateCount。你会在其中存储什么?好吧,假设您已经计算出两个数字的平均值:23,即2.5;如果新的速率为10,则将平均值 ( 2.5 ) 乘以速率计数(在本例中为2)。现在,你有5 个。将此结果添加到新的速率值 ( 10 ) 并将结果除以3

让我们用一个简单的公式来涵盖以上所有内容,

(AverageRating * RateCount + NewRateValue) / (RateCount + 1)
Run Code Online (Sandbox Code Playgroud)

所以(2.5 * 2 + 10) / (2 + 1) = 5

在服务器端(而不是在数据库中)计算平均值,并将平均值存储在列中AverageRating,并将比率计数存储在RateCount列中。

很简单吧?!

编辑

只要不涉及审查、编辑或删除操作,该解决方案就不需要单独存储每个评级。然而,对于这种情况;假设您有一条评分为3的评论,所有者用户希望将其修改为4。那么,重新计算平均评分的公式将是这样的,

(AverageRating * RateCount - OldRateValue + NewRateValue) / RateCount
Run Code Online (Sandbox Code Playgroud)

参考

https://math.stackexchange.com/a/106314