【问题标题】:Is it possible to create a database call outside of a required loop?是否可以在所需循环之外创建数据库调用?
【发布时间】:2015-05-16 22:09:35
【问题描述】:

我正在尝试按使用数据库中的数据创建的平均值来显示和排序数组。我正在从数据库中检索三个变量并从这些值中创建一个平均值。然后将该值放入一个新数组中,以便与其余数据库数据一起排序。

我是否认为在循环中包含 SQL 查询不是一个好主意? (性能问题?)

有没有其他可用的替代方案?我附上了以下代码:

    ^ database connection/query string to retrieve all data...
$result = $stmt_business_list->fetchAll(PDO::FETCH_ASSOC);

$items = array();
    foreach($result as $row){

    $single_business_id = $row['id'];
    $name = $row['name'];
    //Query to get ALL the service, value and quality ratings for certain business
    $test_query = "SELECT * FROM rating WHERE business_id = $single_business_id";
    $test_query_stmt = $dbh->prepare($test_query);
    $test_query_stmt->execute();
    $test_row = $test_query_stmt->fetchAll(PDO::FETCH_ASSOC);
    $total_value = $total_quality = $total_service = 0;

        foreach($test_row as $review)
        {
            $total_value += $review['value'];
            $total_quality += $review['quality'];
            $total_service += $review['service'];
        }

    $bayesian_value = (($set_site_average_review_count * $set_site_average_review_score) + $total_value) / ($set_site_average_review_count + $business_review_count);
    $bayesian_quality = (($set_site_average_review_count * $set_site_average_review_score) + $total_quality) / ($set_site_average_review_count + $business_review_count);
    $bayesian_service = (($set_site_average_review_count * $set_site_average_review_score) + $total_service) / ($set_site_average_review_count + $business_review_count);
    $average_bayesian_rating = ($bayesian_value + $bayesian_quality + $bayesian_service) / 3;
    $average_bayesian_rating = $average_bayesian_rating;

        array_push($items, array(
        "id"=>"$single_business_id",
        "name"=>"$name",
        "value"=>"$total_value",
        "quality"=>"$total_quality",
        "service"=>"$total_service",
        "average"=>"$average_bayesian_rating"));

    echo 
    'Name: '.$name.'<br>
    Value: '.$total_value.'<br>
    Quality: '.$total_quality.'<br>
    Service: '.$total_service.'<br>
    Average: '.$average_bayesian_rating.'<br><br>';
    }
}

该页面将由一个单独的分页脚本拆分,一次仅显示 6 个对象,但随着时间的推移,这可能会发生变化,因此我会尽可能多地关注性能。

【问题讨论】:

  • 你是对的,在循环中运行查询将成为性能瓶颈。通过扩展获取业务列表的原始查询、加入评级表并使用 MySQL 的 AVG 函数和 GROUP BY,可以使用一个 sql 查询来完成所有这些操作。
  • 那么要从原始查询中获取服务、价值和质量,然后只需在循环中进行计算吗?唔!我会试试这个!
  • 其实mysql中的AVG函数可以用来计算平均收视率,如果您要查找每个业务的总评分和评分数,请查看SUM和COUNT函数。让数据库在一个查询中为您完成工作:)
  • 这是我所追求的特殊类型的平均值,这就是问题所在 - 这不是通常的平均值,它是加权的 - '贝叶斯平均值'

标签: php mysql arrays loops


【解决方案1】:

SQL 聚合查询是针对这类事情进行的。

使用这个查询来总结结果

 SELECT b.name, b.id,
        SUM(value)   total_value,
        SUM(quality) total_quality,
        SUM(service) total_service,
        COUNT(*)     review_count,
        avg_reviews_per_biz
   FROM business b
   JOIN ratings r ON b.id = r.business_id
   JOIN (
          SELECT COUNT(DISTINCT business_id) / COUNT(*) avg_reviews_per_biz
            FROM ratings
        ) a ON 1=1                     
  GROUP BY b.name, b.id, avg_review_per_biz

这将为每个商家提供一行,显示总评分和评分数。此结果集将包含以下列

name            business name
  id            business id
  total_value   sum of value ratings for that business
  total_quality sum of quality ditto
  total_service sum of service ditto
  review_count  number of reviews for business "id"
  avg_reviews_per_biz   avg number of reviews per business 

对于查询的所有行,最后一列的值都相同。

然后,您可以一次循环遍历这些行一项业务来进行统计计算。

我无法从你的问题中看出你在哪里得到像 $set_site_average_review_count 这样的变量,所以我无法帮助这些计算。

你会发现SQL聚合查询确实很强大。

【讨论】:

  • 啊,我刚刚明白你想要做什么 - 不知道我将如何处理每个业务的平均值,目前我正在通过查询之外的公式来解决这个问题跨度>
  • 糟糕,average_review_per_biz 中有错字。固定。
  • 查询运行时纠正了拼写错误,但平均值不正确,这就是我选择使用贝叶斯公式的原因,我认为无法在查询内完成?
  • 很多人在查询中做贝叶斯的事情。我怀疑你也可以。通过那个 JOINed 子查询,我试图向您展示如何处理两遍统计计算。这是另一个例子。 plumislandmedia.net/mysql/mean-absolute-deviation
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多