2008-12-04 50 views
3

我目前正在重写一个应用程序,教师可以在线规划课程表。在PHP中使用最佳表示方式/深度树(MySQL/XML /?)

该应用程序指导教师通过为学生创建工作单元的过程。该工具目前在三种状态下使用,但我们计划获得比这更大的作用。

该应用程序的主要抽奖卡之一是,所有的学生成果都预先加载到系统中。这允许教师搜索或浏览并选择在每个工作单元中将满足哪些结果。

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

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

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

表以粗体

H1

ID,名称

H2

号,parent___id(h1_id),名称

H3

ID,parent___id(h2_id),名称

结果

ID,parent___id(h3_id),名称

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

其他比明显无法添加n /层次的层次结构还要难以在不递归查询数据库的情况下显示所有标准的列表。

一旦学生的成绩(和他们的父类别)被添加,他们没有什么理由以任何方式进行修改。主要的要求是它们很容易和有效的阅读。

到目前为止,来自不同学校/州/国家的所有学生成绩都大致遵循了我的假设。这可能并非总是如此。

当然,所有现有数据都必须从当前数据库传输。

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

  • 继续使用数据库中的4个表,选择或者使用recusion或地段时加入

  • 使用嵌套组

  • XML(可能是全球性的XML文件的所有不同套或每个XML文件)

+0

请参阅我的答案http://stackoverflow.com/questions/192220/what-is-the-most-efficientelegant-way-to-parse-a-flat-table-into-a-tree#192462 – 2008-12-04 07:53:18

回答

6

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

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

结果

ID,PARENT_ID,级别,名称

您可以使用递归遍历树的任何特定元素跟踪(你实际上并不需要的水平,但它可以更容易查询)。

替代方案是嵌套集。在这种情况下,你仍然会合并到一个表中,但是使用设置的东西来跟踪级别。

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

读密集型:嵌套集合

写密集型:父树啄

这是因为与嵌套集合,你可以用一个单一的查询,但在重新排序整棵树的成本获取整个树每次插入一个新节点时。

当您刚刚跟踪parent_id时,可以单独移动或删除节点。 PS:我对XML投票不支持。你有相同的递归问题,加上解析数据的开销,以及将它存储在数据库或文件系统中(这会导致并发问题)。

+0

谢谢对于这些建议,有时候你只需要一个新的意见来指出那显而易见的问题。 Cheers :) – Danny 2008-12-04 10:56:21

1

我同意另一张海报 - 嵌套集是我想的方式。

在这里看到:

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

它解释的理论,并将其与你已经在使用 - 这是对邻接扭转真的。它显示了全部的+/-,并且应该帮助您根据项目的所有细节做出决定。

我见过的另一件事(在CakePHP的树行为中)实际上是同时使用两者。当然,它不是很好的表现,但在这个模型下,你插入/删除的东西就像你在邻接时一样,然后有一个方法来重建左/右边的值,让你在嵌套中执行选择集时尚。结果是你可以更容易地插入/删除。

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

+0

我遇到过一个CI类,它允许组合嵌套集和邻接模型,与您可能尝试链接的cakephp版本类似。 我会回来的结果。 – Danny 2008-12-04 10:56:55

0

还有另一种方式是,也许比这里所描述的嵌套组等模式不是“智能”数据库来处理树木,但是这确实是高效和方便:

代替存储项目的水平(或深度),您可以存储的完整路径树,像这样:

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 

那么你可以easyly得到:

  • (纯SQL)与其中母公司=“”条款
  • (纯SQL)的所有直接和间接的孩子用其中一个项目的所有直接子路径LIKE的母公司 - %'子句
  • (PHP)的节点的深度(计数(爆炸( ' - ',$ PATH))

这些功能都够用了在大多数情况下,和相当高效,即使有几个子游戏,只要a你创建好的指数(PK,父母指数,路径指数)。当然,这个解决方案要求删除/移动节点来更新路径...

我希望这有助于!