22

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

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

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

通过创建一个额外的表来存储评级来规范化数据。

这会将评级数据隔离到一个单独的表中,让产品表提供有关可用产品的数据。尽管它需要连接或单独的评级查询。

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

4

3 回答 3

41

强烈建议使用不同的评级表来保持动态。不要担心数百(或数千或数万)个条目,这对数据库来说只是小菜一碟。

建议:

餐桌用品

  • ID
  • 姓名
  • ETC

products_ratings

  • ID
  • 产品编号
  • 评分
  • 日期(如果需要)
  • ip(如果需要,例如防止双重评级)
  • ETC

检索产品的所有评级1234

SELECT pr.rating
FROM products_ratings pr
INNER JOIN products p
  ON pr.productId = p.id
  AND p.id = 1234

产品平均评分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;

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

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
GROUP BY p.id, p.name, p.etc;
于 2010-05-23T17:49:44.090 回答
3

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

于 2010-05-23T17:35:28.743 回答
1

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

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

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

(AverageRating * RateCount + NewRateValue) / (RateCount + 1)

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

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

很简单吧?!

参考

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

于 2021-10-19T13:17:28.417 回答