如何使三重foreach更快

时间:2014-12-01 05:40:09

标签: php mysql foreach

我想获得每个学生每个性别和每个复制品的平均资金。

以下代码的工作进度非常缓慢,处理数据需要一个多月的时间。

如何让它更快?

我试图在查询之前创建一个数组但是失败了。

$link = new mysqli('localhost','root','','table1');
if ($link->connect_errno) {
  echo "Failed to connect to MySQL: (" . $link->connect_errno . ") " . $link->connect_error;
}
$week = [1,3,6,8,11,14,16,19,21,22,26,28,33,35,37,47,55,65,67,70,77,87,89,99,101,122];
$gender = ['M','F'];
$replicate = [1,2,3];
$sum = [];
$relative = [];
foreach ($week as $w) {
  foreach ($gender as $g) {
    foreach ($replicate as $r) {
      sth = $link->query("SELECT * FROM table1 WHERE week ='".$w."' AND gender ='".$g."' AND replicate ='".$r."'");
      $sum=0;
      while ($row=$sth->fetch_assoc()){
        $sum=$sum+$row['value'];
      }
      unset($sql);
      $sql = array();
      unset($sth);
      $sth1 = $link->query("SELECT * FROM table1 WHERE week ='".$w."' AND gender ='".$g."' AND replicate ='".$r."'");
      while ($row1=$sth1->fetch_assoc()) {
        $relative=$row1['value']/$sum;
        $query = "UPDATE table1 SET relative = ".$relative." WHERE week =".$w." AND gender ='".$t."' AND replicate =".$r." AND name=".$row1['name']."";
      }
      $link->query($query);
      echo $query;  
    }
  }
} 
mysqli_close ($link);

2 个答案:

答案 0 :(得分:1)

您可以在SQL中使用“IN()”子句,如下所示。

$week = [1,3,6,8,11,14,16,19,21,22,26,28,33,35,37,47,55,65,67,70,77,87,89,99,101,122];
$gender = ['M','F'];
$replicate = [1,2,3];

$weeks = implode(',',$week);
$genders = implode(',',$gender);
$replicates = implode(',',$replicate);

 $sth = $link->query("SELECT * FROM table1 WHERE week IN ($weeks) AND gender IN ($genders) AND replicate IN ($replicates)");

答案 1 :(得分:1)

我假设$ week,$ gender和$ replicate只是每种类型项目的选择。如果它实际上是一个过滤器,您可以使用另一个答案所描述的IN子句。

在联接更新查询中使用AVG(平均)函数来更新整个表。

UPDATE table1 t1
INNER JOIN (
  SELECT AVG(value) AS avg, week, gender, replicate 
  FROM table1 GROUP BY week, gender, replicate
) AS sq
SET t1.relative = sq.avg 
WHERE t1.week = sq.week AND t1.gender = sq.gender
AND t1.replicate = sq.replicate

在子查询中获取平均值,然后通过加入更新来填充表格。

换句话说:

首先,使用GROUP BY和AVG对整个表进行查询,这样做是将所有值合并为平均值,其中周,性别和复制是相同的。它还会选择这些值,以便它可以在上层查询中匹配它们。

update语句使用子查询中的结果集,并将avg结果复制到relative列(根据您的代码所需),其中周,性别和复制匹配在子查询中选择的值。

<小时/> 编辑:

再看一下,在查询中你似乎想要更像这样的东西:

SELECT SUM(value) AS sum, week, gender, replicate -- (instead of AVG)
...
SET t1.relative = t1.value/sq.sum -- set to their value divided by sum