【问题标题】:reach memory limit with loop inside loop inside loop循环内循环内循环达到内存限制
【发布时间】:2014-01-02 22:53:00
【问题描述】:

免责声明:我知道我的代码中有不推荐使用的 mysql 函数。那在我的待办事项清单上。

我有一个 MySql 选择,让我在房屋预订系统中为不同的项目提供季节。

种类:

Low season: 2010-01-01, 2010-03-01, 100 //meaning start,end,price

这是我的第一个 sql:

while($season_row=mysql_fetch_assoc($season_res)){
    $seasonsArray[$season_row['id_item']][] = array(
        $season_row['season_start'], 
        $season_row['season_end'],
        $season_row['daily_price']
    );
}

这里定义了日期(到达函数YYYY-mm-dd):

function seasonPrice($from,$to,$requested_item){

    $start = round(strtotime($from)/86400)*86400; // like 2008-01-01
    $end = round(strtotime($to)/86400)*86400;     // to 2015-01-01

    $formattedStart = date('Y-m-d', $start);
    $formattedEnd   = date('Y-m-d', $end);

现在我需要在 $seasonsArray 的项目之间循环两个日期,然后检查该项目在特定日期的价格。

我这样做了:

foreach($seasonsArray as $item=>$value){            
    for( $thisDay = $start; $thisDay < $end; $thisDay = $thisDay + 86400){

        foreach($value as $innerValue){     
            $season_start = roundToSeconds($innerValue[0]);
            $season_end = roundToSeconds($innerValue[1]);
            if($thisDay >= $season_start && $thisDay <= $season_end) {  
                $foundPrice[] = round($innerValue[2]);
            }
        }

        $thisSerie[] = array($thisDay * 1000, isset($foundPrice) ? $foundPrice[0] : 0);

        // security check to avoid double assigned seasons to same day
        if(count($foundPrice) > 1){ die('There is double bookings in item: '.$item);}   

        unset($foundPrice);
    }
    $seasonPrices[] = array(
        'data'=> $thisSerie,
        'label'=> 'House ID: '.$item, 
    );  
}

但我得到:Fatal error: Allowed memory size of 100663296 bytes exhausted

有什么建议可以改进我的代码以不需要这么多内存吗?还是有错误而我没有看到?

【问题讨论】:

  • 你在用 seasons 数组做什么?也许您已经可以使用 sql 查询或至少部分简化它来做到这一点,3 嵌套 for 看起来很糟糕
  • @arieljuod 季节数组只是为了从 sql 查询中收集数据。每个房屋项目都有许多季节,例如每年 4/5,开始和结束以及该期间一天的价格。同意 3loops = 不好,但没有更好的方法......
  • 您能否发布一个示例,说明您从数据库中获取的数据以及循环结束时想要的数据?不清楚您想对这些循环做什么,也许一个示例可以提供帮助。我猜你可以简化循环做一个更好的查询,但我不明白你最后想要什么
  • @arieljuod,当然。让我知道这是否有帮助:jsfiddle.net/beNUS/show - 感谢您查看此内容。
  • 不清楚的部分是你想用这些数据做什么,那个循环在 seasonPrice 函数里面?季节价格返回什么?您期望该输入的输出是什么?

标签: php mysql loops


【解决方案1】:

我会生成一系列日期并加入您的季节表,并使用单个查询来获取所需的结果集,例如:

SELECT dates.Date,
       coalesce(s.price, 0) AS price
FROM
  (SELECT a.Date
   FROM
     ( SELECT curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY AS Date, '0' AS price
      FROM
        (SELECT 0 AS a
         UNION ALL SELECT 1
         UNION ALL SELECT 2
         UNION ALL SELECT 3
         UNION ALL SELECT 4
         UNION ALL SELECT 5
         UNION ALL SELECT 6
         UNION ALL SELECT 7
         UNION ALL SELECT 8
         UNION ALL SELECT 9) AS a
      CROSS JOIN
        (SELECT 0 AS a
         UNION ALL SELECT 1
         UNION ALL SELECT 2
         UNION ALL SELECT 3
         UNION ALL SELECT 4
         UNION ALL SELECT 5
         UNION ALL SELECT 6
         UNION ALL SELECT 7
         UNION ALL SELECT 8
         UNION ALL SELECT 9) AS b
      CROSS JOIN
        (SELECT 0 AS a
         UNION ALL SELECT 1
         UNION ALL SELECT 2
         UNION ALL SELECT 3
         UNION ALL SELECT 4
         UNION ALL SELECT 5
         UNION ALL SELECT 6
         UNION ALL SELECT 7
         UNION ALL SELECT 8
         UNION ALL SELECT 9) AS c) a
   WHERE a.Date BETWEEN '$from' AND '$to'
   ORDER BY a.Date) dates
LEFT JOIN seasons s ON dates.Date BETWEEN s.start AND s.END

复杂的内部查询避免了创建临时表(取自generate days from date range)并且可以工作长达1000天,但创建一个临时表就可以了。

【讨论】:

  • 感谢您的关注!我一直在查看您的答案并试图理解它:) 我觉得当我完全理解时,您的答案会提升我的知识。如果您愿意在代码上添加一些内容,那就太好了。无论如何,我真的很高兴有这个建议来学习和学习。谢谢!
【解决方案2】:

看起来你永远不会离开 for 循环。 $start 和 $end 在哪里设置。通过打印出来验证它们的值。

就优化而言,无需每天循环。跳过计算天数的 for 循环,在第二个 foreach 循环中使用 $season_start 和 $season_end 计算天数。

事实上,现在有一个错误,除非 $session_start 和 $session_end 总是相隔一天以上,因为有时事件会在您循环的 24 小时期间发生。

【讨论】:

  • 感谢您查看此内容。我看不出我怎么能跳过白天循环。我从我的 sql 获得的季节只有一天的开始和结束,比如每个季节的 3/4 个月。因此,每年 4/5 开始,结束并在此期间为一天的价格。
猜你喜欢
  • 2012-12-22
  • 2014-06-18
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
相关资源
最近更新 更多