2014-01-02 2 views
0

Отказ от ответственности: Я знаю, что у меня в моем коде устарели функции mysql. То есть на моем todo.достичь предела памяти с петлей внутри цикла внутри цикла

У меня есть выбор 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 и затем проверить pri в этом конкретном дне.

Я сделал это с:

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

Любое предложение о том, где мой код может быть улучшен, чтобы не нужно так много памяти? Или есть ошибка, и я не вижу ее?

+0

Что вы делаете с массивом сезонов? возможно, вы уже можете сделать это с помощью sql-запроса или, по крайней мере, частью этого, чтобы упростить его, 3 вложенные, чтобы выглядеть как-то плохое. – arieljuod

+0

@arieljuod the seasons array - это просто сбор данных из SQL-запроса. Каждый элемент дома имеет много сезонов, например 4/5 в год, с началом и ценой за день в течение этого периода. Согласитесь с 3loops = нехорошо, но не видите лучшего способа ... – Rikard

+0

можете ли вы разместить пример данных, которые вы получаете из базы данных и данных, которые вы хотите в конце циклов? это не clea, что вы хотите делать с этими циклами, может быть, пример может помочь. Я предполагаю, что yo может упростить цикл, делающий лучший запрос, но я не понимаю, чего вы хотите в конце – arieljuod

ответ

2

Я бы генерировать диапазон дней и присоединиться к вашей таблице сезонов, а также использовать один запрос для получения желаемого resulset, например:

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 дней, но создание временной таблицы было бы неплохо.

+0

Спасибо, что посмотрели на это! Я смотрел на ваш ответ и пытался понять его :) Я чувствую, что ваш ответ улучшит мои знания, когда я полностью пойму это. Если вы хотите добавить некоторые вещи в код отлично. Во всяком случае, я очень рад, что это предложение учиться и учиться. Благодаря! – Rikard

+0

Получил работу! Еще раз спасибо! – Rikard

0

Похоже, что вы никогда не покидаете цикл for. Где начинаются $ start и $ end. Проверьте их значения, распечатав их.

Что касается оптимизации, то нет необходимости проходить через каждый день. Пропустите цикл for, который учитывает дни и использует $ season_start и $ season_end для вычисления дня во втором цикле foreach.

Фактически, есть ошибка прямо сейчас, если только $ session_start и $ session_end не отличаются друг от друга, потому что когда-нибудь событие произойдет между 24-часовыми периодами, которые вы зацикливаете.

+0

Спасибо, что посмотрели на это. Я не вижу, как я могу пропустить дневной цикл. Сезоны, которые я получаю от моего sql, имеют только начало и конец дня, например, 3/4 месяца в каждом сезоне. Так что 4/5 в год с началом и ценой за день в течение этого периода. – Rikard

Смежные вопросы