【问题标题】:Order database results by bayesian rating按贝叶斯评级排序数据库结果
【发布时间】:2012-01-03 03:13:28
【问题描述】:

我什至不确定这是否可能,但在以“丑陋”的方式进行之前我需要确认:)

因此,“结果”是数据库中的帖子,存储方式如下:

  • posts 表,其中包含所有重要内容,例如 ID、标题、内容
  • 帖子元表,其中包含其他帖子数据,例如评分 (this_rating) 和投票数 (this_num_votes)。这个数据是成对存储的,表有3列:post ID/key/value。它基本上是 WordPress 表结构。

我想要的是拉出评分最高的帖子,根据这个公式排序:

br = ( (avg_num_votes * avg_rating) + (this_num_votes * this_rating) ) / (avg_num_votes + this_num_votes)

我从 here 偷来的。

avg_num_votesavg_rating 是已知变量(每次投票都会更新),因此不需要计算。

这可以通过 mysql 查询来完成吗?还是我需要获取所有帖子并使用 PHP 进行排序?

【问题讨论】:

    标签: php mysql database sorting sql-order-by


    【解决方案1】:

    我已更改接受的答案的数据和查询。

    数据现在是来自 5 星评级系统的数据样本。
    该函数现在可以正确使用所有帖子的平均值。

    不同之处在于这些平均值的计算,而不是 PHP,它们是在 SQL 中计算的,目的是为了回答。

    您可以在 SQL Fiddle 上看到它的实际效果:http://sqlfiddle.com/#!9/84d8b/2/2


    更新后的查询

    新小提琴:http://sqlfiddle.com/#!9/3cdfe/1/2

    SET @avg_total_votes  := (SELECT AVG(meta_value) FROM postmeta WHERE meta_key ='this_num_votes');
    SET @avg_total_rating := (SELECT AVG(meta_value) FROM postmeta WHERE meta_key ='this_rating');
    
    SELECT  posts.ID,
            posts.title, 
            getmeta_votes.meta_value AS votes,
            getmeta_rating.meta_value AS rating,
            ( ( (@avg_total_votes * @avg_total_rating) + (getmeta_votes.meta_value * getmeta_rating.meta_value) ) / ( @avg_total_votes + getmeta_votes.meta_value ) ) AS factor
    FROM posts
    LEFT JOIN postmeta AS getmeta_votes  ON posts.ID = getmeta_votes.post_id  AND getmeta_votes.meta_key  = 'this_num_votes'
    LEFT JOIN postmeta AS getmeta_rating ON posts.ID = getmeta_rating.post_id AND getmeta_rating.meta_key = 'this_rating'
    WHERE NOT getmeta_votes.meta_value = 0 AND NOT getmeta_rating.meta_value = 0
    ORDER BY factor DESC;
    

    我发现这个查询构造要快得多,前一个查询在 2,000 多个帖子数据集(1,000,000+ wp_postmeta 行)上工作了 2 小时,直到终止。

    这个运行时间为 0.04 秒。

    【讨论】:

    • 这不适用于我的真实数据集(一个包含数千个帖子的 WordPress 数据库),我将在一段时间内优化查询并更新我的答案。
    • 好的,查询现已更新并且运行良好。我希望这会对某人有所帮助,并节省一些我不得不花在上面的时间。干杯!
    【解决方案2】:

    数据栈交换链接:

    https://data.stackexchange.com/stackoverflow/s/2137/order-database-results-by-bayesian-rating

    SELECT id,title,( AVG(this_num_votes) * AVG(this_rating) + this_num_votes * this_rating )
         / ( AVG(this_num_votes) + this_num_votes ) as br
    FROM posts
    LEFT JOIN (
    SELECT DISTINCT post_id,
    (SELECT meta_value FROM postmeta WHERE postmeta.post_id = pm.post_id AND meta_key ='this_num_votes') as this_num_votes,
    (SELECT meta_value FROM postmeta WHERE postmeta.post_id = pm.post_id AND meta_key ='this_rating') as this_rating
    FROM postmeta pm ) as newmeta ON posts.ID = newmeta.post_id
    GROUP BY id,title,this_num_votes,this_rating
    ORDER BY br DESC
    

    【讨论】:

    • this_num_votesthis_rating 不是列字段,而是记录。这些名称是key 列中的记录值。
    • 例如,此查询将获取所有具有评级/投票元键的帖子:SELECT * postmeta LEFT JOIN posts ON (posts.ID = post_id) WHERE meta_key IN('this_rating', 'this_num_votes') $order_here LIMIT 0,10
    • 太棒了,谢谢:) 只是一个小错误,br 公式不正确,应该是(($avg_num_votes * $avg_rating) + (this_num_votes * this_rating)) / ($avg_num_votes + this_num_votes) as br。平均投票和评分是全球性的,与当前帖子无关
    • 因为 * 具有更高的优先级,我认为它们是相同的
    • 是的,我指的不是操作顺序,而是AVG(...) 的值,这是错误的。计算所有帖子的平均投票/评分,它是一个 php 变量:)
    【解决方案3】:

    开始吧:

    // Bayesian Rating Calc
    $theItem = $_GET[’id’];
    if($theItem) {
    // all items votes and ratings
    $result = mysql_query(”SELECT AVG(item),AVG(vote) FROM itemvotes WHERE vote>’0′ GROUP BY item”) or die(mysql_error());
    $row = mysql_fetch_row($result);
    $avg_num_votes = $row[0];
    $avg_rating = $row[1];
    
    // this item votes and ratings
    $result = mysql_query(”SELECT COUNT(item),AVG(vote) FROM itemvotes WHERE item=’$theItem’ AND vote>’0′”) or die(mysql_error());
    $row2 = mysql_fetch_row($result);
    $this_num_votes = $row2[0];
    $this_rating = $row2[1];
    
    if(!$row OR !$row2)
    $br = “_”;
    else
    $br = number_format( ((($avg_num_votes * $avg_rating) + ($this_num_votes * $this_rating))/($avg_num_votes + $this_num_votes)), 1, ‘.’ );
    } // end of if item selected
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 1970-01-01
      • 2012-11-22
      • 2011-04-08
      • 1970-01-01
      • 2013-11-27
      • 2017-11-14
      相关资源
      最近更新 更多