【问题标题】:How to get structed result using nested set in MySQL and PHP?如何使用 MySQL 和 PHP 中的嵌套集获取结构化结果?
【发布时间】:2010-04-07 01:12:43
【问题描述】:

深度没有限制。

如何得到结构化的分支甚至整棵树?

定义来自这里:Managing Hierarchical Data in MySQL

【问题讨论】:

    标签: php mysql nested-sets


    【解决方案1】:

    我不确定它是否完全符合您的要求,但值得注意的是,您可以通过使用 GROUP_CONCAT 并扩展,在 MySQL 中获得整个树,每个路径一行,每个路径作为字符串,如下所示关于来自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

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

    【讨论】:

    • 使用此解决方案,您可以在 foreach() 中使用格式良好的 eval() 以在 2 行代码中快速解析为嵌套数组。安全方面,这假设类别数据是完全可信的。
    【解决方案2】:

    我使用了一种类似但不完全相同的方法,该方法还保留了对子项中父项的引用;这使得从数据中构建树结构变得更加容易。如果这有用,我可以将用于提取数据的代码发布到 PHP 中的树中。

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

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

    我已尝试将其剥离以演示基本要素,因此可能存在一些拼写错误等,但您应该明白这一点。关键部分是

    • 按“lft ASC”对查询进行排序,这样您将始终在处理子节点之前处理父节点。
    • 按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;
    }   
    

    【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      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 连接需要很长时间才能执行。

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

      【讨论】:

      • 本文中技术的重点是避免左连接/多个查询。这里的问题不是查询(使用所描述的方法,您所需要的只是“SELECT * FROM nested_category ORDER BY lft ASC”),而是之后如何将查询结果转换为结构。
      • 好的,在这种情况下忽略我的帖子。对不起
      【解决方案5】:

      我必须告诉您有关使用 php.. 无需递归即可处理树结构的方法。我认为您对标准 php 库 (SPL) 非常了解。您可以使用迭代器来解决您的问题。

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

      这里是 SPL 文档的链接。以下是您上面的 Mysql 链接示例的一些解决方案:- 通过简单地从表中检索您的数组,您可以处理它们并显示为您的偏好

      对于:- 邻接表模型

      您可以使用“RecursiveIteratorIterator”,它将显示所有结果,包括所有子项。

      如果你只想给孩子们看。您可以使用 “父迭代器”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-12-09
        • 2014-10-20
        • 2016-04-30
        • 2017-01-19
        • 2018-04-14
        • 2018-08-02
        • 2023-04-05
        相关资源
        最近更新 更多