php - 如何优化 SQL 查询以避免 while() 嵌套子查询?

标签 php mysql while-loop subquery

我搜索了一些东西来优化以下嵌套 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(限制为 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.="&bull; ".$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.="&bull; ".$tag_name."<br/>";
  }

有什么想法或建议,可以做得更好、更快、更轻(而不是像傻朋克那样更强;))?

一些LEFT JOINRIGHT JOIN或将tag1、tag2...tag5字段放入ITEM表中,或其他? 但请注意,项目可能有 0 到 5 个关联的标签...

最佳答案

评论太长了,所以我在这里发帖。

当谈到在输出之前在 PHP 中缓存数据库结果时,我总是会有点犹豫,因为这对于 *data*base 和 PHP 的关系来说并不“直观”。

在这种情况下,特别是如果您有一个非常大的 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 "&bull; ".$res_tag['name']."<br/>";
  }
}

上面的代码没有经过测试,但我想你可以明白。

关于php - 如何优化 SQL 查询以避免 while() 嵌套子查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14949845/

相关文章:

php - 将表从开发迁移到生产

Php、MySql - 多个数据库连接和 mysql_insert_id()

php - 订单日期查询,语法错误

php - Doctrine : OneToOne entity relationship doesn't work

java - 扫描到文件中

php - 大型 MySQL 查询超时

c++ - 结束交互式程序会导致无限循环

php - MySQL 查询过滤

MySQL 获取逗号分隔值

php - 使用php pdo向数据库中插入记录