【问题标题】:Best way to represt n/ depth tree for use in PHP (MySQL / XML / ?)表示用于 PHP 的 n/ 深度树的最佳方式(MySQL / XML / ?)
【发布时间】:2008-12-04 06:49:25
【问题描述】:

我目前正在重写一个教师可以在线规划课程的应用程序。

该应用程序指导教师完成为学生创建作业单元的过程。该工具目前在三个州使用,但我们计划扩大规模。

该应用程序的主要抽奖卡之一是所有学生的成绩都预加载到系统中。这使教师可以搜索或浏览并选择每个工作单元要达到的结果。

当我最初设计系统时,我假设所有学生的成绩都遵循类似的层次结构。也就是说,有命名的嵌套容器,然后是结果。

我输入的原始结果集是三层的。因此,我的数据库具有以下结构:

===========================

粗体表

h1

身份证,姓名

h2

id、父___id (h1_id)、姓名

h3

id、父___id (h2_id)、姓名

结果

id、父___id (h3_id)、姓名

===========================

除了明显无法添加 n/ 层次结构之外,这种方法还使得在不递归查询数据库的情况下难以显示所有标准的列表。

一旦添加了学生成绩(及其父类别),就几乎没有理由对其进行任何修改。主要要求是它们易于阅读且高效。

到目前为止,来自不同学校/州/国家/地区的所有学生成绩都大致符合我的假设。情况可能并非总是如此。

所有现有数据当然必须从当前数据库传输过来。

鉴于上述情况,我存储所有不同学生成绩的最佳方式是什么?下面列出了我的一些想法。

  • 在选择使用 recusion 或很多连接时继续使用数据库中的 4 个表

  • 使用嵌套集

  • XML(所有不同集合的全局 XML 文件或每个集合的 XML 文件)

【问题讨论】:

标签: php mysql xml search tree


【解决方案1】:

我不知道您实际上需要 4 个表。

如果您有一个跟踪 parent_id 的表和一个级别,您可以拥有无​​限级别。

结果

id、parent_id、级别、名称

您可以使用递归来跟踪任何特定元素的树(您实际上不需要级别,但使用它可以更容易查询)。

替代方法是嵌套集。在这种情况下,您仍将合并到单个表,但使用设置的内容来跟踪级别。

使用哪一个取决于您的应用程序。

阅读密集型:嵌套集

写密集型:父树的东西

这是因为使用嵌套集,您可以通过单个查询检索整个树,但代价是每次插入新节点时都会重新排序整个树。

当您只跟踪 parent_id 时,您可以单独移动或删除节点。

PS:我对 XML 投反对票。您有同样的递归问题,加上解析数据以及将其存储在数据库或文件系统中的开销(这将导致并发问题)。

【讨论】:

  • 感谢您的建议,有时您只需要一个新的意见来指出明显的问题。干杯:)
【解决方案2】:

我同意其他海报的观点 - 我认为嵌套集是要走的路。

看这里:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

它解释了理论并将其与您已经使用的理论进行了比较——这实际上是对邻接的一种扭曲。它显示了所有这些中的 +/-,并且应该可以帮助您根据项目的所有细微之处做出决定。

我看到的另一件事(在 CakePHP 的树行为中)实际上是同时使用两者。当然它的性能不是很好,但是在这个模型下,你可以像使用邻接一样插入/删除东西,然后有一种方法可以运行来重建左/右边缘值,以允许你在嵌套中进行选择集时尚。结果是您可以更轻松地插入/删除。

http://book.cakephp.org/view/91/Tree

【讨论】:

  • 我遇到了一个 CI 类,它允许组合嵌套集和邻接模型,类似于您链接到的 cakephp 版本,我可以尝试一下。我会把结果发回来。
【解决方案3】:

还有另一种方法来处理数据库中的树,它可能不如此处描述的嵌套集和其他模式“智能”,但这确实有效且简单:

您可以将完整路径存储在树中,而不是存储项目的级别(或深度),如下所示:

A
  B
  C
    D
  E

会这样存储:

item  |  parent  |  path
----------------------------
A     |  NULL    |  A
B     |  A       |  A--B
C     |  A       |  A--C
D     |  C       |  A--C--D
E     |  A       |  A--E

那么你就可以轻松搞定:

  • (纯 SQL)带有 where parent = '' 子句的项目的所有直接子项
  • (纯 SQL)具有 where 路径 LIKE 'PARENT--%' 子句的所有直接和间接子代
  • (PHP) 节点的深度 (count(explode('--',$path))

只要您创建了良好的索引(PK、父索引、路径索引),这些功能在大多数情况下都足够好,并且性能相当好,即使有多个子级别也是如此。当然,这个解决方案在删除/移动节点以更新路径时要求很高......

我希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2019-06-25
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多