用单个查询recursion类别?

我有一个网站的文章和部分,每个部分可以有一个父节,尽可能多的例如:

subject 1 -subject 2 --subject 3 -subject 4 --subject 5 --subject 6 ---subject 7 subject 8 subject 9 

等等..

现在,我想要recursion地获取它们,通过php和mysql来做什么是最有效的方法?

Tnx在先进。

如果树不是太大,可以使用一些聪明的引用简单地在PHP中构build树。

 $nodeList = array(); $tree = array(); $query = mysql_query("SELECT category_id, name, parent FROM categories ORDER BY parent"); while($row = mysql_fetch_assoc($query)){ $nodeList[$row['category_id']] = array_merge($row, array('children' => array())); } mysql_free_result($query); foreach ($nodeList as $nodeId => &$node) { if (!$node['parent'] || !array_key_exists($node['parent'], $nodeList)) { $tree[] = &$node; } else { $nodeList[$node['parent']]['children'][] = &$node; } } unset($node); unset($nodeList); 

这将给你$tree的树结构与子$tree中的子$tree

我们用相当大的树(>> 1000项)完成了这个操作,它比在MySQL中执行recursion查询更加稳定。

这取决于你如何存储你的数据。 在MySQL.com上有一篇很好的文章,叫做“ pipe理MySQL中的分层数据” 。

那么,你可以在一个查询中获取数组中的所有类别,如你所知:

 $query = "SELECT `name`,`id` from `table`"; 

在数组中,可以使用一些嵌套循环来构build树。 它不会很快,但比使用recursion查询更简单。 而且,您可以caching构build的树,而不必每次都重build它。

你可以看看这个话题: 如何从昨天打开的mysql获取分层菜单,并且是大致相同的事情。

矿用一个查询recursion…以及

无需多次调用数据库即可存储分层数据的recursion方法

我想使用recursion也是由于其简单,但像你我想删除recursion查询的开销。 我的逻辑是这样说的,你只是将数据库中的负载移动到内存上,这取决于数据库结果的大小,但是我没有做任何真正的可伸缩性testing,所以我不知道它有多大的影响,非recursion方法。

我不能保证我没有犯任何语法错误,但这应该与一个查询。

 class menuSystem{ var $menu; var $db; #this variable is my db class assigned from the construct, I havent written the construct in, I can if you need it function startNav(){ $this->db->runQuery("select * from table order by parent asc"); $menu = array(0 => array('children' => array())); while ($data = $this->db->fetchArray()) { $menu[$data['category_id']] = $data; $menu[(is_null($data['parent']) ? '0' : $data['parent'] )]['children'][] = $data['category_id']; } $this->menu = $menu; $nav = '<ul>'; foreach($menu[0]['children'] as $child_id) { $nav .= $this->makeNav($menu[$child_id]); } $nav .= '</ul>'; } function makeNav($menu){ $nav_one = '<li>'."\n\t".'<a href="#">'$menu['name'].'</a>'; if(isset($menu['children']) && !empty($menu['children'])) { $nav_one .= "<ul>\n"; foreach($menu['children'] as $child_id) { $nav_one .= $this->makeNav($this->menu[$child_id]); } $nav_one .= "</ul>\n"; } $nav_one .= "</li>\n"; return $nav_one; } 

}

编辑: 对不起,我在我的代码中使用这个作为一个类,并认为我已经设法把它从一个类为你,但忘了我需要$ this->菜单

更新: 我认为下面是一个类,现在,抱歉这么长的答案

 $result = mysql_query("select * from table order by parent_id asc"); $menu = array(0 => array('children' => array())); while ($data = mysql_fetch_array($result)) { $menu[$data['category_id']] = $data; $menu[(is_null($data['parent_id']) ? '0' : $data['parent_id'] )]['children'][] = $data['category_id']; } $global_menu = $menu; $nav = '<ul>'; foreach($menu[0]['children'] as $child_id) { $nav .= makeNav($menu[$child_id]); } $nav .= '</ul>'; function makeNav($menu) { global $global_menu; $nav_one = '<li>'."\n\t".'<a href="#">' . $menu['name'].'</a>'; if(isset($menu['children']) && !empty($menu['children'])) { $nav_one .= "<ul>\n"; foreach($menu['children'] as $child_id) { $nav_one .= makeNav($global_menu[$child_id]); } $nav_one .= "</ul>\n"; } $nav_one .= "</li>\n"; return $nav_one; } 

希望它有帮助

卢克

文章的第一部分只涉及到四个层面,最后一部分不是我想要做的。

我的结构是这样的:

 +-------------+----------------------+--------+ | category_id | name | parent | +-------------+----------------------+--------+ | 1 | test | NULL | | 2 | subject1 | 1 | | 3 | subject2 | 1 | | 4 | subject3 | 2 | | 5 | subject4 | 4 | +-------------+----------------------+--------+ 

我不想使事情复杂化,我想以最简单的方式来完成,而是以最有效的方式获取数据。

如果假设你的表有idid_parrent和name字段

 function tree($id) { $query = "SELECT `name`,`id` from `table` WHERE `id_parrent` = '$id'"; $result = mysql_query($query); if(mysql_num_rows($result) != 0) { echo "<ul>"; while($row = mysql_fetch_array($result)) { echo "<li>",$row[name],"</li>"; tree($row[id]); } echo "</ul>"; } } 

所以你会得到整棵树

 category1 category1_1 category1_2 category1_2_1 category1_2_2 category1_3 ........................... 

从你的例子到每个类别保存在另一个领域的完整path:
1 – 1
2 – 1.2
3 – 1.2.3
4 – 1.4
5 – 1.4.5
6 – 1.4.6
7 – 1.4.6.7
8 – 8
9 – 9

然后用ORDER BY在该字段上查询

我有这个问题的一个很好的解决scheme。

不使用recursion 。 它需要对数据库进行单个查询

我刚刚在这里回答了类似的问题:

https://stackoverflow.com/questions/2871861#3368622

谢谢。