2010-08-06 23 views
2

J'ai une table qui contient une liste de catégories et une autre table qui contient une liste de produits dans chaque catégorie.MYSQL: Au lieu d'utiliser des instructions SELECT dans une boucle while - quelles sont mes options?

par exemple.

CatID | Cat_Name 
---------------- 
1  | Books 
2  | CDs 

et

ProductID | Product_Name  | CatID 
------------------------------------ 
1   |The Bible   | 1 
2   |The Koran   | 1 
3   |90s Greatest Hits | 2 
4   |80s Greatest Hits | 2 

ce que je veux faire est d'obtenir

<ul> 
<li>Books</li> 
    <ul> 
    <li>The Bible</li> 
    <li>The Koran</li> 
    </ul> 
<li>Cds</li> 
    <ul> 
    <li>90s Greatest Hits </li> 
    <li>00s Greatest Hits </li> 
    </ul> 
</ul> 

sans faire (PHP)

$query = mysql_query("SELECT ... FROM categories") 

while($row = mysql_fetch_assoc($query)): 

$query2 = mysql_query("SELECT ... FROM products WHERE catId = $row['CatId']) 

endwhile; 

Comment puis-je déplacer loin d'utiliser tout imbriqué/SELECT, puis-je le faire efficacement avec un seul y - et comment puis-je accéder aux données pertinentes en utilisant PHP? J'ai eu l'impression que si vos tables devenaient assez volumineuses, plusieurs requêtes SQL ralentiraient votre page, et donc pour optimiser le chargement de la page, vous devriez essayer de réduire le nombre de requêtes?

+4

Utilisation de l'instruction JOIN – Codler

Répondre

6

sélectionner tous les produits et les noms de catégorie à l'aide REJOIGNEZ

select * from category c, products p where c.catID = p.catID order by p.catID 

fetch et groupe résultats

$products_by_cat = array(); 
foreach(fetch(....) as $record) 
    $products_by_cat[$record->catName][] = $record; 

vous obtiendrez un tableau 2-D comme

[books] => array(bible, koran) 
[CDs] => array(cd1, cd2, ....) 

affiche ce tableau avec deux boucles imbriquées

foreach($products_by_cat as $cat => $products) 
    <li> $cat <ul> 
    foreach($products as $p) 
     <li> $p->name </li> 
    </li></ul> 
2

Vous pouvez sélectionner toutes les données à la fois en utilisant une jointure ...

SELECT * 
    FROM category JOIN products ON catgegory.CatID = products.CatID 
    ORDER BY products.CatID; 

mais je ne peux vraiment voir quoi que ce soit terriblement mal avec votre approche actuelle.

+1

Je suis d'accord, je ne pense pas que ce soit plus efficace que votre approche actuelle – Sebs

+3

Sûrement, moins une connexion db est ouverte, mieux c'est. –

+1

@Brian Hooper: Oui mais comment accéder aux données pour produire la liste non ordonnée avec PHP? @Ash Burlaczenko: C'est ce que je pensais? – Ash

0
SELECT * FROM category JOIN products USING(CatID); 
1

La réponse de user187291 est très bonne. Je tiens à souligner que vous pouvez imprimer votre liste sans boucler le jeu de résultats plus d'une fois. Cela peut être utile si vous avez beaucoup d'objets.

Pour ce faire, assurez-vous que le résultat de la requête est trié par catégorie. Créez une variable pour garder une trace de la 'catégorie actuelle' et réglez-la sur quelque chose qui ne sera pas un identifiant de catégorie, comme 'x'. Parcourez le résultat et chaque fois que le CatID ne correspond pas à la valeur de votre catégorie, vous savez que vous avez modifié les catégories et que vous devez imprimer l'en-tête de la catégorie. Réinitialisez la valeur de catégorie actuelle à la nouvelle valeur CatID.

Cela suffit dans certaines situations de liste. Dans votre cas, vous devrez également déterminer quand une catégorie se termine afin que vous puissiez terminer vos listes correctement. Vous pouvez le faire en regardant en avant dans le tableau des résultats pour voir si la catégorie suivante correspond à la valeur de votre catégorie actuelle et agir en conséquence.

Avec seulement quelques catégories, peu importe comment vous le faites. Si vous avez des milliers de lignes avec beaucoup de données, cette méthode peut être un peu plus rapide et utiliser moins de mémoire.Il est un peu plus difficile à comprendre logiquement que la méthode de user187291. Mais il ne fait que boucler les données une seule fois, et il ne crée pas de doublon des données, ce qui peut être pratique si vous avez des mégaoctets de données à faire défiler.

+0

Ceci est une excellente explication, en particulier la partie à propos de l'avenir dans le tableau. Bien expliqué. Merci – Ash