3

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

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

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

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

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

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

粗体表

h1

身份证,姓名

h2

id,父母___id(h1_id),姓名

h3

id, 父母___id (h2_id), 姓名

结果

id,父母___id(h3_id),姓名

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

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

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

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

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

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

  • 在使用数据库中使用4个表继续使用回收或大量连接时

  • 使用嵌套集

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

4

3 回答 3

6

我不知道您实际上需要 4 张桌子。

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

结果

id、parent_id、级别、名称

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

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

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

阅读密集型:嵌套集

写密集型:父树事物

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

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

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

于 2008-12-04T07:17:58.280 回答
1

我同意另一张海报 - 我认为嵌套集是要走的路。

看这里:

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

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

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

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

于 2008-12-04T08:42:10.950 回答
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

那么你可以很容易地得到:

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

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

我希望这有帮助!

于 2009-11-04T17:15:13.143 回答