我有一个包含类别列表的表,另一个表包含每个类别中的产品列表。
e.g。
CatID | Cat_Name
----------------
1 | Books
2 | CDs
和
ProductID | Product_Name | CatID
------------------------------------
1 |The Bible | 1
2 |The Koran | 1
3 |90s Greatest Hits | 2
4 |80s Greatest Hits | 2
我想做的是获取
<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>
不做(PHP)
$query = mysql_query("SELECT ... FROM categories")
while($row = mysql_fetch_assoc($query)):
$query2 = mysql_query("SELECT ... FROM products WHERE catId = $row['CatId'])
endwhile;
如何摆脱使用嵌套的while / SELECT语句,我可以使用一个查询有效地完成 - 以及如何使用PHP访问相关数据?
编辑:我的印象是,如果您的表变得非常大,多个SQL查询会降低您的页面速度,因此为了优化页面加载,您应该尝试减少查询次数?< / p>
答案 0 :(得分:6)
使用JOIN
选择所有产品和类别名称select * from category c, products p where c.catID = p.catID order by p.catID
获取并分组结果
$products_by_cat = array();
foreach(fetch(....) as $record)
$products_by_cat[$record->catName][] = $record;
你会得到像
这样的二维数组 [books] => array(bible, koran)
[CDs] => array(cd1, cd2, ....)
使用两个嵌套循环输出此数组
foreach($products_by_cat as $cat => $products)
<li> $cat <ul>
foreach($products as $p)
<li> $p->name </li>
</li></ul>
答案 1 :(得分:2)
您可以使用加入一次选择所有数据...
SELECT *
FROM category JOIN products ON catgegory.CatID = products.CatID
ORDER BY products.CatID;
但我现在无法看到你当前的方法有什么特别的错误。
答案 2 :(得分:1)
user187291的答案非常好。我想指出,您可以打印列表而不会多次循环遍历结果集。如果您有很多项目,这可能很有用。
为此,请确保按类别排序查询结果。创建一个变量来跟踪“当前类别”并将其设置为不属于类别ID的内容,例如“x”。循环结果,每当CatID与您当前的类别值不匹配时,您就知道您已更改类别并需要打印类别标题。将当前类别值重置为新的CatID值。
在某些列表情况下这已经足够了。在您的情况下,您还需要确定类别何时结束,以便您可以正确结束列表。您可以通过在结果数组中预先查看下一个类别是否与当前类别值匹配并相应地采取相应措施来执行此操作。
只有几个类别,你怎么做也没关系。如果您有数千个包含大量数据的行,则此方法可以更快一些并且使用更少的内存。逻辑上比用户187291的方法更难理解。但它只会循环遍历数据一次,并且它不会创建数据的副本,如果您有数兆字节的内容可以循环使用,这可能很方便。
答案 3 :(得分:0)
SELECT * FROM category JOIN products USING(CatID);