Я немного искал что-то, чтобы оптимизировать следующие вложенные запросы while()
, но, к сожалению, я не могу его адаптировать для своего случая.Как оптимизировать SQL-запрос, чтобы избежать() вложенных подзапросов?
Давайте представим следующие отношения к базе данных:
ITEM 0,5---1,n ITEM_TAG 1,n---0,n TAG
ITEM (id, name, ...)
ITEM_TAG (id_item, id_tag)
TAG (id, name, ...)
Теперь мы хотим, чтобы все элементы с их СТП (ограниченные по 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 punk;))?
LEFT JOIN
, RIGHT JOIN
или поместить tag1, tag2 ... tag5 в таблицу ITEM или другую? Но обратите внимание, что ITEM могут иметь от 0 до 5 TAG, связанных ...
Я немного колебался, когда говорил о получении результатов из БД и кешировании их в PHP перед выходом; но вы можете попробовать свой текущий подход с помощью MySQLi/PDO и подготовленного оператора, поэтому вам нужно только один раз подготовить «SELECT id, name FROM tag ...» и иметь относительно быструю производительность без восстановления вашей логики. – Passerby
Спасибо за ваш ответ, но я думаю, что цикл запроса будет таким же? даже с некоторыми MySQLi или PDO, doctrine ... – Valky
Вам понадобятся два оператора: '$ item = $ mysqli-> prepare (" SELECT id FROM item ... "); $ tag = $ mysqli-> prepare (" SELECT name FROM tag ... WHERE id_item =? ")'. Вам все равно нужно выполнить внутренний цикл '$ tag', но' $ tag' был подготовлен, поэтому в базу данных он отличается от прямого 'mysql_query' и, следовательно, лучшей производительности. – Passerby