2010-11-02 6 views
2

Dans CodeIgniter, j'ai le modèle suivanttableaux multidimensionnels

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; 
} 

Le problème est que cela se traduit par plusieurs requêtes à la table SQL augmentant le temps d'exécution de manière significative (la pagination n'est pas une option)

I Je veux pouvoir transmettre les résultats de la première requête à la deuxième requête sous la forme d'un tableau, de sorte que je n'aurais qu'un seul accès à la base de données, puis reconstruire un tableau à partir des résultats.

Comment dois-je réécrire ce code (la deuxième partie)? Est-ce que ce sera plus rapide (je suppose)?

EDIT

reconstruction de la matrice des résultats est ce qui me flummoxing.

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

ce que je veux sans doute, mais je manquerais le saut

Répondre

2

Vous pouvez utiliser la requête interne ici. Il est situation idéale pour que -

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; 
} 
+0

Merci, utilisé vos conseils pour ma solution –

2

Vous devez utiliser JOIN pour ce faire. Cela va décharger l'exécution de la requête sur le serveur. Je ne peux pas vous donner trop de détails plus sans savoir comment votre base de données est structuré, mais il faut vérifier les docs sur 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

Je pensais plus sur le modèle de http://www.phpbuilder.com/board/showthread.php?t=10373847.Regardera JOIN si –

2

Une autre option serait de faites vos wheres dans la boucle et déplacez l'exécution de requête en dehors du 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; 
+0

Essayé votre méthode, renvoie le résultat en tant que tableau dimensionnel «simple» (pas vraiment unique) J'ai besoin d'un tableau multidimensionnel. –

+0

Ahh désolé, je me concentrais sur les appels db réducteurs, vous pourriez alors boucler à travers ce tableau et construire votre tableau md. –

+0

Pourriez-vous me montrer comment reconstruire le tableau afin qu'il retourne un résultat similaire au code initial –

0

OK cela a pris un peu de travail, et je devais aussi faire quelques ajustements à mon avis

Le problème peut être décomposé en deux composantes principales

1) Faire passer les résultats de la première requête dans un tableau à la seconde en utilisant where_in

2) Reorder/regroupent les résultats de la première matrice par item_id

Mon code précédent a été fait le deuxième élément implicitement

Voici donc ce que je faisais (limites, les compensations, les commandes ont été découpées pour améliorer readablity)

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 
} 

Ainsi, le nombre de requêtes ont été coupées de ~ 10 à 2. Sur mon ordinateur local, cela économise ~ 50 msec/page, bien que je ne sois pas sûr de la façon dont cela fonctionnera pour les bases de données plus volumineuses.

+0

PS La contribution de tout le monde est appréciée, j'ai marqué Alpesh comme la bonne réponse. D'autres suggestions? –

Questions connexes