用单个查询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 | +-------------+----------------------+--------+
我不想使事情复杂化,我想以最简单的方式来完成,而是以最有效的方式获取数据。
如果假设你的表有id , id_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
谢谢。