我搜索了一些优化以下嵌套while()
查询的内容,但不幸的是我无法根据我的情况进行调整。
让我们假设以下数据库关系:
ITEM 0,5---1,n ITEM_TAG 1,n---0,n TAG
ITEM (id, name, ...)
ITEM_TAG (id_item, id_tag)
TAG (id, name, ...)
现在,我们希望所有的ITEM都有他们的TAG(限制在5)。
我所做的是需要优化的丑陋追随者:
$req=mysql_query("SELECT id, name FROM ITEM WHERE 1 ORDER BY id DESC");
while($res=mysql_fetch_array($req))
{
$items.="<h1>".$res['name']."</h1>";
$req_tag=mysql_query("SELECT id, name
FROM TAG, ITEM_TAG
WHERE ITEM_TAG.id_item='".$res['id']."'
AND ITEM_TAG.id_tag=TAG.id
LIMIT 5");
while($res_tag=mysql_fetch_array($req_tag))
$items.="• ".$res_tag['name']."<br/>";
}
另一种方法是选择所有项目及其标签,并使用数组过滤它们,如下所示:
$req=mysql_query("SELECT ITEM.id AS 'item_id',
ITEM.name AS 'item_name',
TAG.id AS 'tag_id',
TAG.name AS 'tag_name'
FROM ITEM, ITEM_TAG, TAG
WHERE ITEM_TAG.id_item=ITEM.id
AND ITEM_TAG.id_tag=TAG.id
ORDER BY ITEM.id DESC");
while($res=mysql_fetch_array($req))
{
$listTag[$res['item_id']][$res['tag_id']]=$res['tag_name'];
$listItem[$res['item_id']]=$res['item_name'];
}
foreach($listItem as $item_id=>$item_name)
{
$items.="<h1>".$val."</h1>";
foreach($listTag[$id_item] $tag_id=>$tag_name)
$items.="• ".$tag_name."<br/>";
}
任何想法或建议,做得更好,更快,更轻(并且不像Daft朋克更强;))?
某些LEFT JOIN
,RIGHT JOIN
或将tag1,tag2 ... tag5字段放入ITEM表或其他字段?
但请注意,ITEM可能有0到5个TAG关联...
答案 0 :(得分:1)
评论时间太久了,所以我在这里发帖。
在输出之前谈到缓存DB结果时,我总是会有点犹豫,因为对于 data * base和PHP的关系来说,这不是“直观的”。 / p>
在这种情况下,特别是如果你有一个非常大的ITEM
表,你将在PHP中缓存很多字符串,然后才能输出。
所以我认为你可以使用当前的逻辑,并利用准备好的声明:
$req=$mysqli->query("SELECT id, name FROM ITEM WHERE 1 ORDER BY id DESC");
$tag=$mysqli->prepare("SELECT id, name FROM tag, item_tag WHERE item_tag.id_item=? AND item_tag.id_tag=tag.id LIMIT 5");
$tag->bind_param("i",$tid);
while($res=$req->fetch_assoc())
{
echo "<h1>".$res['name']."</h1>";
$tid=intval($res["id"]);
$tag->execute();
$req_tag=$tag->get_result();
while($res_tag=$req_tag->fetch_assoc())
{
echo "• ".$res_tag['name']."<br/>";
}
}
上面的代码没有经过测试,但我认为你可以理解。