我正在尝试设计一个包含部分的表,每个部分包含任务,每个任务包含子任务等等。我想在一张桌子下做。请让我知道可扩展的最佳单表方法。我对数据库设计很陌生。另外请建议如果单表不是最好的方法那么可能是最好的方法来做到这一点。我正在使用db2。
答案 0 :(得分:1)
简单地说,我会说使用1表来完成任务。
除了所有其他各种属性外,每个任务都应该有一个主要标识符,另一个列可以选择包含其父任务的标识符。
如果您使用的是DB2 for z / OS,那么您将使用recursive query with a common table expression。否则你可以使用hierarchical recursive query in DB2 for i,或者in DB2 for LUW(Linux,Unix,Windows)。
其他需要更多表格的设计,每个表格都专注于任务的某个部分:子任务关系,可能会不必要地引入问题或限制。
答案 1 :(得分:0)
有几种方法可以做到这一点。
一个想法是使用两个表:章节和任务
两者之间可能存在一对多的关系。 Task表可以设计为具有TaskId和ParentTaksId的树,这意味着您可以拥有深层次的任务(子任务的子任务和子任务等)。除根任务之外的每个任务都将具有父级。
我想你也可以通过使用一个表来解决这个问题,你只需要在我上面描述的Task表中添加一个section列。
答案 2 :(得分:0)
如果你打算把所有东西放在一张桌子上,虽然从长远来看方便效率低下。这意味着您将在数据库中存储不必要的重复数据组,这些数据组根本不是处理器和内存友好的。它实际上会违反Normalization rules,更具体地说是1st Normal Form
,它表示不应该在您的表格中找到重复的组。它实际上也会违反3rd Normal Form
,这意味着非主键与另一个非主键没有(过渡)依赖关系。
为了给你一个插图,我会把你的设计放在一张桌子上。虽然我会猜测可能的领域,但只是忍受它,因为这是为了讨论。看下面的图形:
如果您查看上面的图片(虽然这个图片相当小,您可以下载图片并亲眼看到它),SectionName
,Taskname
,TaskInitiato
r,{{ 1}}和TaskStartDate
是不必要的重复,正如我前面提到的那样违反了TaskEndDate
。
其次,1st Normal Form
,Taskname
,TaskInitiator
和TaskStartDate
在功能上依赖于TaskID,而TaskID不是主键而不是SectionID,在这种情况下应该是主要的键(如果在单独的表上)。这违反了第3范式,表示不应该有过渡依赖或非主键应该依赖
另一个非主键。
虽然有些情况你必须去标准化,但我相信这个应该归一化。根据我自己的估计,您的设计中应该包含三个表格,即TaskEndDate
,Sections
和Tasks
,这些表格如下所示。
SubTasks
与Section
相关,也就是说,某个部分可能有多个Tasks
。
Tasks
与Task
相关,也就是说,Sub-Tasks
可能有多个Task
。
答案 3 :(得分:0)
如果我理解正确的原始海报不知道,将需要多少级别的层次结构(因此“等等”)。他的问题是创造一种可以容纳任何深度结构的设计。
Imho这是一个复杂的问题,没有一个答案。在实施这样的设计时,您需要计算以下因素:
结构是否相当稳定? (写了多少?) 这个结构多久会被阅读一次? 需要进行哪些操作? (获取给定对象的所有子对象?获取父对象?获取直接子对象?)
如果结构是常量您可以使用嵌套集模型(http://en.wikipedia.org/wiki/Nested_set_model)
这样,表格有一个“左”和“右”列。父对象的左右列包含其任何子对象的值。
通过这种方式,您可以使用如下查询列出对象的所有子项:
SELECT child.id
FROM table AS parent
JOIN table AS child
ON child.left BETWEEN parent.left AND parent.right
AND child.right BETWEEN parent.left AND parent.right
WHERE
parent.id = @searchId
此设计可以非常快速地阅读,但在结构更改时也非常昂贵(例如,将子项添加到任何对象时您将不得不使用高于插入的'right'值更新任何对象一个)。
如果你需要能够实时更改结构,你应该使用带有两个表的设计 - 一个持有对象,第二个是结构(类似于parentId,childId,differenceInHierarchyLevels)。