如何使用MySQL和PHP中的嵌套集获取结构化结果?

时间:2010-04-07 01:12:44

标签: php mysql nested-sets

深度没有限制。

如何获得结构化分支甚至整个树?

定义来自此处:Managing Hierarchical Data in MySQL

5 个答案:

答案 0 :(得分:5)

我不确定这是你要求的,但是值得注意的是你可以使用GROUP_CONCAT获得整个树,每条路径一行,每条路径作为字符串,如下所示:并从http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

扩展“检索单一路径”示例
SELECT 
  GROUP_CONCAT(parent.name ORDER BY parent.lft ASC SEPARATOR '|') 
FROM nested_category AS node
     CROSS JOIN nested_category AS parent 
WHERE 
  node.lft BETWEEN parent.lft AND parent.rgt 
GROUP by node.id 
ORDER BY node.lft;

这将输出树中每个节点的路径。

请注意,nested_category AS node CROSS JOIN nested_category AS parent相当于nested_category AS node, nested_category AS parent

这个用途指定字符串'|'作为分隔符,如果你想将它分解为一个路径元素数组&你知道你的数据中没有你可以指定的字符串。

答案 1 :(得分:2)

我使用了一种类似但不完全相同的方法,它也保留了对孩子父母的引用;这使得从数据构建树结构更容易。如果这很有用,我可以发布用于在P​​HP中将数据提取到树中的代码。

@Marc,所描述的数据结构不一定用于进行集合操作;它只是简化了结构的使用。如果要获取整个数据树,并且每个记录只存储指向父记录的指针,则需要递归查询数据库以获取完整的数据树。如果您使用那里描述的方法,那么您可以在一个查询中提取整个集合。

编辑:这是构建树结构的代码如果您维护一个孩子 - >父参考以及lft / right东西。我更喜欢这样做,因为如果您只想获得树的单个级别的直接后代,它实际上仍然更快。

我试图将其剥离以展示必需品,因此可能存在一些拼写错误,但您应该明白这一点。关键部分是

  • 按“lft ASC”命令查询,这样您就可以在子节点之前处理父节点。
  • 按ID存储对每个节点的引用;这样,该节点的任何子节点都可以轻松找到它并将其自身添加到父节点。
  • 遍历结果,按ID存储每个ID的引用(如上所示),并将此节点添加到其父节点的子节点。

无论如何,这是代码 -

<?php
$children = mysql_query('SELECT * FROM nested_category ORDER BY lft ASC');

/* Get the first child; because the query was ordered by lft ASC, this is
   the "root" of the tree */
$child          = mysql_fetch_object($children);
$root           = new StdClass;
$root->id       = $child->folderID;
$root->children = array();
/* Store a reference to the object by the id, so that children can add
   themselves to it when we come across them */
$objects        = array($root->id => $root);

/* Build a tree structure */
while ($child = mysql_fetch_object($children)) {
    /* Create a new wrapper for the data */
    $obj           = new StdClass;
    $obj->id       = $child->id;
    $obj->children = array();
    /* Append the child to the parent children */
    $parent = $objects[$child->parent];
    $parent->children[] = $obj;
    $objects[$obj->id] = $obj;
}   

答案 2 :(得分:0)

即使mysql端数据结构有些奇特,仍然使用常规查询方法检索数据。发出适当的select语句,遍历结果,并将其填充到PHP数组中。虽然我不知道你为什么要这样做,因为在PHP中设置操作比在MySQL中设置操作要困难得多。

答案 3 :(得分:0)

看看你的链接,我会用左连接做。查看检索完整树的示例。

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4 FROM category AS t1 LEFT JOIN category AS t2 ON t2.parent = t1.category_id LEFT JOIN category AS t3 ON t3.parent = t2.category_id LEFT JOIN category AS t4 ON t4.parent = t3.category_id WHERE t1.name = 'ELECTRONICS';

您需要为要包含的每个层次级别提供LEFT JOIN。 然后可以通过php将结果解析为任何所需的数据结构。只需忽略NULL个结果。

| ELECTRONICS | TELEVISIONS | TUBE | NULL |

| ELECTRONICS | TELEVISIONS | LCD | NULL |

| ELECTRONICS | TELEVISIONS | PLASMA | NULL |

| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |

| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS | NULL |

| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL |

当你有一个深层结构时,这将是一个更糟糕的方法,因为当需要连接许多表时,MySQL连接需要很长时间才能执行。

我希望我没有误解你的问题。

答案 4 :(得分:0)

我必须告诉你有关使用php进行树结构工作的方法..没有递归。我认为你非常熟悉标准的PHP库(SPL)。您可以使用迭代器来解决您的问题。

http://www.php.net/~helly/php/ext/spl/

这是SPL文档的链接。以下是Mysql链接的上述示例的一些解决方案: - 只需从表中检索您的数组,您就可以对它们进行处理并显示为您的首选项

用于: - 邻接列表模型

您可以使用“RecursiveIteratorIterator”来显示包括所有孩子在内的所有结果。

如果你只想展示孩子。您可以使用   “ParentIterator”