Многомерные массивы - PullRequest
       5

Многомерные массивы

2 голосов
/ 02 ноября 2010

В Codeigniter у меня есть следующая модель

function get_item_history($id)
{  
  //from metadata_history get item_id and corresponding metadata
  $this->db->from('metadata_history')->where(array('id'=>$id, 'current_revision'=> "TRUE"));
  $query = $this->db->get();
  $result = $query->result_array(); //store this in an array

  // loop through the array
  foreach( $result as $key => $row ) 
  {
   $array = array('item_id'=>$row['item_id'], 'current_revision'=> "TRUE");
   $this->db->from('history')->where($array);
   $query = $this->db->get();
   $row['items'] = $query->result_array(); //
   $result[$key] = $row; 
  }

  return $result;
}

Проблема в том, что это приводит к тому, что несколько запросов к таблице SQL значительно увеличивают время выполнения (разбиение на страницы не поддерживается)

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

Как мне переписать этот код (вторая часть)? Будет ли это быстрее (я так полагаю)?

EDIT

Перестройка массива из результатов - вот что сбивает меня с толку.

http://www.phpbuilder.com/board/showthread.php?t=10373847

это то, что я, вероятно, хочу, но не могу прыгнуть

Ответы [ 4 ]

2 голосов
/ 02 ноября 2010

Другим вариантом было бы включить ваши циклы в цикл и переместить выполнение запроса за пределы foreach:

// loop through the array
foreach( $result as $key => $row )  
{
        $array = array('item_id'=>$row['item_id'], 'current_revision'=> "TRUE");
        $this->db->or_where($array);
}

$query = $this->db->get();
$row['items'] = $query->result_array(); //
$result[$key] = $row;
2 голосов
/ 02 ноября 2010

Вы можете использовать внутренний запрос здесь.Это идеальная ситуация для этого -

function get_item_history($id)
{  

// Here the above requirement can be achieved in a single query.

$sql = "select * from history h 
where h.item_id IN (select item_id from metadata_history mh where mh.id = $id 
AND mh.current_revision = TRUE) AND h.current_revision = TRUE";

$result = $this->db->query($sql);

//Return whichever column of result you want to return or process result if you want.

$result;
}
2 голосов
/ 02 ноября 2010

Вы должны использовать JOIN для этого. Это разгрузит выполнение запроса на сервер. Я не могу дать вам слишком много подробностей, не зная, как устроена ваша база данных, но посмотрите документы на JOIN:

http://dev.mysql.com/doc/refman/5.0/en/join.html

http://www.webdesign.org/web-programming/php/mysql-join-tutorial.14876.html

http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php

0 голосов
/ 03 ноября 2010

ОК, это заняло определенную работу, и мне также пришлось внести некоторые коррективы, на мой взгляд

Таким образом, проблему можно разбить на два основных компонента

1) Передать результаты первого запроса в виде массива второму, используя where_in

2) Переупорядочить / перегруппировать результаты первого массива на item_id

Мой предыдущий код выполнял второй компонент неявно

Итак, вот что я сделал (ограничения, смещения, упорядочение были вырезаны для улучшения читабельности)

function get_item_history($id)
{  
 //from metadata_history get item_id and corresponding metadata
 $this->db->from('metadata_history')->where(array('id'=>$id, 'current_revision'=> "TRUE"));
 $query = $this->db->get();
 $result_query1 = $query->result_array(); //store this in an array




foreach ($result_query1 as $key-> $row){
$result[$row['item_id']]['meta_info'] = $row; //the first query contains meta info, that must be passed to the view
$selected_id_array[] = $row['item_id'];  //Create a  array to pass on to the next query
$result[$row['item_id']]['items'] = array(); //declare an array which will hold the results of second query later
}


$this->db->select('h.*');
$this->db->from('history h');
$this->db->where_in('h.item_id', $selected_id_array);
$this->db->where(array('h.current_revision' => 'TRUE'));
$query = $this->db->get();

$row = $query->result_array();


        foreach ($row as $key => $datarow) {

        $result[$datarow['item_id']]['items'][] = $datarow; //populate the array we declared earlier with results from second query
}




return $result; // Now this variable holds an array which is indexed by item id and contains the results of second query 'grouped' by item_id
 }

Таким образом, количество запросов было сокращено с ~ 10 до 2. На моей локальной машине это экономит ~ 50 мсек / страницу, хотя я не уверен, как это будет работать для больших баз данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...