存储和;使用多个父节点查询分层数据

时间:2010-08-27 12:36:20

标签: sql database database-design data-structures

我一直在做相当多的搜索,但未能找到关于该主题的许多资源。我的目标是存储您在甘特图中找到的调度数据。因此,存储数据的一个示例可能是:

Task Id | Name    | Duration
1         Task A    1
2         Task B    3
3         Task C    2

Task Id | Predecessors
1         Null
2         Null
3         1
3         2

任务C等待任务A和任务B完成。

所以我的问题是:存储此类数据并有效查询的最佳方法是什么?对于这种事情有什么好的资源吗?有大量关于树结构的信息,但是一旦你添加了多个父母,就很难找到信息。顺便说一句,我正在使用SQL Server和.NET来完成这项任务。

3 个答案:

答案 0 :(得分:2)

使用邻接列表模型:

chain

task_id  predecessor
3        1
3        2

和此查询查找给定任务的所有前任:

WITH    q AS
        (
        SELECT  predecessor
        FROM    chain
        WHERE   task_id = 3
        UNION ALL
        SELECT  c.predecessor
        FROM    q
        JOIN    chain c
        ON      c.task_id = q.predecessor
        )
SELECT  *
FROM    q

获取每项任务的最长父项的持续时间:

WITH    q AS
        (
        SELECT  task_id, duration
        FROM    tasks
        UNION ALL
        SELECT  t.task_id, t.duration
        FROM    q
        JOIN    chain с
        ON      c.task_id = q.task_id
        JOIN    tasks t
        ON      t.task_id = c.predecessor
        )
SELECT  task_id, MAX(duration)
FROM    q

答案 1 :(得分:2)

您的问题与关系基数的概念有关。所有关系都有一些基数,它表示作为其成员的关系每一侧的潜在实例数,或者可以参与关系的单个实例。例如,对于人们来说(对于大多数生物,我猜,除了极少数例外),亲子关系的基数为2 to zero or many,这意味着父母一方需要两个父母,并且可以零个或多个孩子(也许应该是2 to 1 or many

在数据库设计中,通常情况下,一方面具有1(一),(或零或一)的任何东西都可以很容易地用两个表来表示,每个实体一个表(有时只需要一个表)请参阅注释**)和表中“许多”一侧的外键列,该列指向另一个表,将该实体保留在“一”侧。

在您的情况下,您有many to many关系。 (一个Task可以有多个前驱,每个前任当然可以是多个任务的前身)在这种情况下需要第三个表,其中每一行实际上代表两个任务之间的关联,表示一个是前一个任务。其他。通常,此表旨在仅包含两个父表的主键的所有列,并且它自己的主键是两个父主键中所有列的组合。在你的情况下,它只有两列,taskId和PredecessorTaskId,这对Ids在表中应该是唯一的,所以它们一起形成复合PK。

在查询时,为了避免在有多个连接时对父表中的数据列进行重复计算,只需将查询基于父表...例如,要查找最长父项的持续时间,   假设您的关联表名为TaskPredecessor

  Select TaskId, Max(P.Duration)
  From Task T Join Task P
     On P.TaskId In (Select PredecessorId 
                     From TaskPredecessor
                     Where TaskId = T.TaskId)

**注意。如果关系中的两个实体具有相同的实体类型,则它们都可以位于同一个表中。规范(luv that word)示例是一个员工表,其中包含工人与主管之间的多对一关系......由于主管也是一名员工,工人和主管都可以在同一[员工]表中,以及实际情况可以使用外键(称为SupervisorId)建模,该外键指向同一个表中的另一行,并包含该员工主管的员工记录的ID。

答案 2 :(得分:1)

检查“SQL设计模式”一书中的“分层加权总计”模式,或“SQL中的树和层次结构”中的“物料清单”部分。

总之,图表具有双重聚合功能。您在每个路径中的节点上执行一种聚合,而在另一个路径中执行另一种聚合。例如,找到两个节点之间的最小距离对于求和是最小的。分层加权总查询(又名物料清单)是沿每条路径的数量的乘积,以及沿每条替代路径的总和:

     
       with TCAssembly as (
          select Part, SubPart, Quantity AS factoredQuantity
          from AssemblyEdges
          where Part = ‘Bicycle’
          union all
          select te.Part, e.SubPart, e.Quantity * te.factoredQuantity
          from TCAssembly te, AssemblyEdges e
          where te.SubPart = e.Part
       ) select SubPart, sum(Quantity) from TCAssembly
       group by SubPart