如何从数据库中的表生成树结构?
Posted
技术标签:
【中文标题】如何从数据库中的表生成树结构?【英文标题】:How can I generate a tree structure from a table in a database? 【发布时间】:2009-03-10 16:47:08 【问题描述】:我正在尝试从数据库中的表生成树结构。该表是扁平存储的,每条记录都有一个 parent_id 或 0。最终目标是生成一个选择框和一个节点数组。
我目前的代码是:
function init($table, $parent_id = 0)
$sql = "SELECT id, $this->parent_id_field, $this->name_field FROM $table WHERE $this->parent_id_field=$parent_id ORDER BY display_order";
$result = mysql_query($sql);
$this->get_tree($result, 0);
print_r($this->nodes);
print_r($this->select);
exit;
function get_tree($query, $depth = 0, $parent_obj = null)
while($row = mysql_fetch_object($query))
/* Get node */
$this->nodes[$row->parent_category_id][$row->id] = $row;
/* Get select item */
$text = "";
if($row->parent_category_id != 0)
$text .= " ";
$text .= "$row->name";
$this->select[$row->id] = $text;
echo "$depth $text\n";
$sql = "SELECT id, parent_category_id, name FROM product_categories WHERE parent_category_id=".$row->id." ORDER BY display_order";
$nextQuery = mysql_query($sql);
$rows = mysql_num_rows($nextQuery);
if($rows > 0)
$this->get_tree($nextQuery, ++$depth, $row);
它几乎可以工作,但不完全。谁能帮我完成它?
【问题讨论】:
几乎可以工作是什么意思?什么有效,什么无效? 如何聪明地提问:catb.org/~esr/faqs/smart-questions.html 【参考方案1】:你几乎可以肯定,不应该继续你目前的道路。如果您的树变得稍微大一点,您尝试使用的递归方法几乎肯定会破坏您的性能。如果您打算经常阅读树,您可能应该查看嵌套集合结构而不是邻接列表。
使用嵌套集,您可以通过单个查询轻松检索正确嵌套的整个树。
有关树木的讨论,请参阅这些问题。
Is it possible to query a tree structure table in MySQL in a single query, to any depth?
Implementing a hierarchical data structure in a database
What is the most efficient/elegant way to parse a flat table into a tree?
【讨论】:
【参考方案2】: $this->nodes[$row->parent_category_id][$row->id] = $row;
这一行正在破坏您的 ORDER BY display_order。改成
$this->nodes[$row->parent_category_id][] = $row;
我的下一个问题是其中的 $row->parent_category_id 部分。不应该只是 $row->parent_id 吗?
编辑:哦,我没有仔细阅读您的来源。摆脱 WHERE 子句。一次阅读整个表格。您需要再次对树进行后期处理。首先,您将数据库读入数组列表。然后你递归地处理数组来做你的输出。
您的数组应如下所示:
Array(0 => Array(1 => $obj, 5 => $obj),
1 => Array(2 => $obj),
2 => Array(3 => $obj, 4 => $obj),
5 => Array(6 => $obj) );
function display_tree()
// all the stuff above
output_tree($this->nodes[0], 0); // pass all the parent_id = 0 arrays.
function output_tree($nodes, $depth = 0)
foreach($nodes as $k => $v)
echo str_repeat(' ', $depth*2) . $v->print_me();
// print my sub trees
output_tree($this->nodes[$k], $depth + 1);
output:
object 1
object 2
object 3
object 4
object 5
object 6
【讨论】:
【参考方案3】:我认为是这里的这一行:
if($row->parent_category_id != 0)
$text .= " ";
应该是:
while ($depth-- > 0)
$text .= " ";
你只是缩进一次,而不是它应该缩进的次数。
还有这一行:
$this->get_tree($nextQuery, ++$depth, $row);
应该是:
$this->get_tree($nextQuery, $depth + 1, $row);
请注意,您可能应该遵循其他答案中的建议,一次抓取整个表,然后立即处理它,因为通常您希望尽量减少到数据库的往返次数(有几个使用方式更优化的用例,例如,如果您有一棵非常大的树,并且正在选择其中的一小部分,但我怀疑这里是这种情况)
【讨论】:
以上是关于如何从数据库中的表生成树结构?的主要内容,如果未能解决你的问题,请参考以下文章