2010-09-28 9 views
2

Je voudrais écrire ce qui suit comme une instruction MySQL SELECT pour réduire le nombre de requêtes nécessaires pour obtenir l'information, mais je ne suis pas sûr de savoir comment l'écrire.Comment dois-je écrire cette requête?

J'ai deux tables - balises et books_tags (une table de jonction de relations many-to-many). La sortie finale, je veux imprimerait comme suit:

<label for="formFiltertag1"><input type="checkbox" name="tag[]" value="1" id="formFiltertag1" class="rank90" /> PHP (15)<br /></label> 

Lorsque le texte est le nom de la balise (tags.name) et le nombre de parens est le nombre de la fréquence ID de la balise apparaît dans la table de jonction (COUNT (books_tags.tag_id)). L'ID et la valeur d'entrée seront dynamiques en fonction du champ tags.id. À l'origine, je pensais lancer une requête qui récupérait toutes les informations de la table de variables, puis utiliser une boucle foreach pour exécuter une requête de comptage distincte pour chacune d'elles, mais au fur et à mesure que le nombre de variables augmentait lourd rapidement.

Voici un exemple que je l'ai écrit maintenant (en utilisant le modèle ActiveRecord de CodeIgniter) ...

Le modèle:

function get_form_tags() { 
    $query = $this->db->get('tags'); 
    $result = $query->result_array(); 
    $tags = array(); 
    foreach ($result as $row) { 
     $this->db->select('tag_id')->from('books_tags')->where('tag_id', $row['id']); 
     $subResult = $this->db->count_all_results(); 
     $tags[] = array('id' => $row['id'], 'tag' => $row['tag'], 'count' => $subResult); 
    } 
    return $tags; 
} 

Le contrôleur:

function index() { 
    $this->load->model('browse_model', 'browse'); 
    $tags = $this->browse->get_form_tags(); 

    $data['content'] = 'browse/browse'; 
    $data['tags'] = $tags; 
    $this->load->view('global/template', $data); 
} 

La vue (condensée):

<?php foreach ($tags as $tag) : ?> 
<label for="formFiltertag<?php echo $tag['id'] ?>"><input type="checkbox" name="tag[]" value="<?php echo $tag['id'] ?>" id="formFiltertag<?php echo $tag['id'] ?>" class="rank<?php echo $tag['count'] ?>" /> <?php echo $tag['tag'] . ' (' . $tag['count'] . ')' ?><br /></label> 
<?php endforeach; ?> 

Cela fonctionne, mais comme je l'ai dit, il va créer beaucoup plus de requêtes que nécessaire pour faire le travail. Sûrement il y a un meilleur moyen. Penny pour vos pensées?

Merci beaucoup, Marcus

Répondre

2
select t, coalesce(btc.Count, 0) as Count 
from tags t 
left outer join (
    select tagid, count(*) as Count 
    from books_tags 
    group by tagid 
) btc on t.tagid = btc.tagid 
+0

Cela fonctionne avec quelques modifications mineures. Merci pour l'aide. Est-ce que quelqu'un arrive à savoir comment écrire ce genre de déclaration compliquée en utilisant les méthodes ActiveRecord? – Marcus

1

$result retourne un tableau de tableaux, où array_combine() attend un tableau de chaînes.

+0

Bonne information - merci. J'ai maintenant réécrit mes exemples de code ci-dessus. – Marcus

Questions connexes