I searched a bit for something to optimize the following nested while() queries, but unfortunately I can't adapt it for my case.
Let's imagine the following database relationships :
ITEM 0,5---1,n ITEM_TAG 1,n---0,n TAG
ITEM (id, name, ...)
ITEM_TAG (id_item, id_tag)
TAG (id, name, ...)
Now, we want to get all the ITEMs with their TAGs (limited at 5).
What I've done is the ugly following wich needs to be optimized :
$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/>";
}
Another way could be to select all the items and their tags and filter them with an array, like the following :
$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/>";
}
Any idea or advise, to do it better, faster, lighter (and not stronger as Daft punk ;)) ?
Some LEFT JOIN, RIGHT JOIN or puting tag1, tag2... tag5 fields into ITEM table, or other ?
But do note that ITEMs could have 0 to 5 TAGs associated...
SELECT id,name FROM tag...once and have a relatively fast performance without rebuilding your logic.$item=$mysqli->prepare("SELECT id FROM item...");$tag=$mysqli->prepare("SELECT name FROM tag...WHERE id_item=?"). You'll still need to execute$taginside loop, but$taghas been prepared, so to database it's quite different than directmysql_query, and thus a better performance.