1

可能重复:
是否可以在单个查询中查询 MySQL 中的树结构表到任何深度?

我创建了一个管理区域,它使用 php 从 mysql 数据库中提取数据并将结果显示在表格中。基本上它显示一个父类别,然后是它下面的第一个子类别,然后是第三级子类别/主题。

它工作得很好,但由于我是 mysql 和 php 的新手,我确信代码需要改进以节省数据库资源,因为在构建表时我使用 3 个 while 循环,并且在每个循环中进行一个 mysql 查询,我是肯定是错误的方法。

有人可以为我提供一些帮助,以最好的方式做到这一点吗?

这是代码:

           $query = mysql_query("SELECT * FROM categories WHERE
parent_id is null
order by cat_id asc;", $hd)
or die ("Unable to run query");       

while ($row = mysql_fetch_assoc($query)) {
echo '<tr style="font-weight:bold;color:green;"><td>'. $row    ['cat_id'].'</td><td>'.$row['cat_name'].'</td><td>'.$row    ['parent_id'].'</td><td>'.$row['active'].'</td><td>'.$row    ['url'].'</td><td>'.$row['date_updated'].'</td></tr>' ;

$query2 = mysql_query("SELECT * FROM categories WHERE
                (active = 'true' AND parent_id = ".$row    ['cat_id'].")
                order by cat_id asc;", $hd)
      or die ("Unable to run query");
while ($row2 = mysql_fetch_assoc($query2)) {
echo '<tr style="font-weight:bold;"><td>'. $row2['cat_id'].'</td><td>'.$row2    ['cat_name'].'</td><td>'.$row2['parent_id'].'</td><td>'.$row2    ['active'].'</td><td>'.$row2['url'].'</td><td>'.$row2    ['date_updated'].'</td></tr>' ;
    $query3 = mysql_query("SELECT * FROM categories WHERE
                (active = 'true' AND parent_id = ".$row2    ['cat_id'].")
                order by cat_id asc;", $hd)
      or die ("Unable to run query");
      while ($row3 = mysql_fetch_assoc($query3)) {
echo '<tr><td>'. $row3['cat_id'].'</td><td>'.$row3['cat_name'].'</td><td>'.$row3    ['parent_id'].'</td><td>'.$row3['active'].'</td><td>'.$row3    ['url'].'</td><td>'.$row3['date_updated'].'</td></tr>' ;

}
}
}

编辑

好的,所以我做了一些研究,这就是我所在的位置:

可能对于一个小型数据库,我的方法很好。

对于使用数组存储数据的更大数据库可能意味着我需要使用可能会占用太多内存的递归方法。很想听听人们的想法,它是否仍然比在嵌套的 while 循环中循环 db 查询更好?

我找到了以下线程,其中没有递归且只有一个查询的答案。不确定是否需要在当前设计中添加位置列: 如何通过 PHP 和 mysql 构建无限级别的菜单

如果我使用嵌套集模型而不是邻接模型重建设计,那么 mysql 查询将以所需的顺序返回结果,但是维护嵌套集设计超出了我的考虑范围,我认为这太过分了。

而已。如果有人对此有任何意见,请添加到对话中。必须有一种成功的方法,因为大量的 Web 应用程序必须需要这种要求。

4

2 回答 2

1

我认为你可以做这样的事情:

SELECT * FROM categories
WHERE active = 'true'
ORDER BY parent_id, cat_id

这将为您提供按 parent_id 排序的所有类别,然后按 cat_id。然后,您将获取结果集并从中构建一个多维数组。然后,您可以像当前一样循环遍历该数组以输出类别。

虽然从数据库访问的角度来看这更好,但它也会消耗更多内存,因为您需要将这个更大的数组保留在内存中。所以这确实是一个你需要考虑的权衡。

于 2012-11-29T19:43:31.520 回答
0

那里有很多要解决的问题,但我只会解决您关于减少查询的问题。我建议一起摆脱 WHERE 子句,并在 while 循环中使用 if 语句。使用外部变量来保存与特定条件匹配的所有结果,然后在循环后立即将它们全部回显。像这样的东西(为了简洁起见,我把你的一堆东西放在变量中)

//before loop
$firstInfoSet = '';
$secondInfoSet = '';
$thirdInfoSet = '';

//in while loop

if($parentID == NULL)
{
  $firstInfoSet.= $yourFirstLineOfHtml;
}

if($active && $parentID == $catID) // good for query 2 and 3 as they are identical
{
  $secondInfoSet.= $yourSecondLineOfHtml;
  $thirdInfoSet.= $yourThirdLineOfHtml;
}

//after loop
echo $firstInfoSet . $secondInfoSet . $thirdInfoSet;

您现在可以进行任何类型的分组,如果需要,可以轻松修改它们,并将结果放在您想要的任何位置。

--EDIT-- 在更好地理解了这个问题之后......

$query = mysql_query("SELECT * FROM categories order by cat_id asc;", $hd);
$while ($row = mysql_fetch_assoc($query)){
   if($row['parent_id'] == NULL){
      //echo out your desired html from your first query 
   }
   if($row['active'] && $row['parent_id']== $row['cat_id']){
      //echo out your desired html from your 2nd and 3rd queries
   }
}
于 2012-11-29T20:21:34.083 回答