【问题标题】:How do I model product ratings in the database?如何在数据库中为产品评级建模?
【发布时间】:2010-05-23 17:29:06
【问题描述】:

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

在 products 表中创建两列,分别存储票数和总票数。使用这些列在运行时或使用查询获取平均值。

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

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

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

哪种方法最好,归一化还是非归一化?

【问题讨论】:

    标签: mysql database-design rating-system


    【解决方案1】:

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

    建议:

    产品

    • 身份证
    • 姓名

    表格products_ratings

    • 身份证
    • 产品标识
    • 评分
    • 日期(如果需要)
    • ip(如果需要,例如防止双重评级)

    检索产品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;
    

    【讨论】:

    • 感谢 Alec,您的方法更有意义。但我还必须考虑如何将它与用户评论最好地结合起来。因此,用户不仅可以评价产品,还可以发表评论。我想我可以将评级表转换为评论表......基本上只是扩展它的功能。谢谢
    • 这种方法刚刚让我遇到了一个问题:如果我把它变成一个“评论”表,那么大多数用户可能只会投票,而不一定要添加评论。这将在表格中留下很多空单元格,其中应该包含评论标题和评论文本。这是个问题吗?
    • @Mel:使用上述方法,您还应该创建一个单独的评论表并使用连接,与评级相同。因此,您的典型查询将获取产品、评级和评论。
    • @Mel:您可以像 Tom 建议的那样创建另一个表。但是,添加评级,或者添加评级和一些文本是非常相似的事情。在这种情况下,我会将它们组合在一个表中以防止出现冗余,因为将它们分开并没有真正的优势。空列不占用空间,不影响速度;很好(只要它们具有适当的功能,就是这种情况)。这与在产品表中添加“注释”列相同,但并非每个产品都可能具有或需要注释。
    • 我在这里看到了一个问题,例如我需要列出所有产品,并且评分可以为 0,也意味着没有特定产品的评分。我们应该如何处理?
    【解决方案2】:

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

    【讨论】:

    • 大卫,我通过取平均评分(voteSum/voteCount)来规避这个问题。如果我决定强调最新产品,我可以先按发布日期排序,然后按评分排序。但一般来说,我并不关心产品的年龄。
    • 值得考虑的一点!
    【解决方案3】:

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

    现在,解决方案,在您的产品表中再添加两列: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

    【讨论】:

    • 高效选择
    猜你喜欢
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    相关资源
    最近更新 更多