我一直在做相当多的搜索,但未能找到关于该主题的许多资源。我的目标是存储您在甘特图中找到的调度数据。因此,存储数据的一个示例可能是:
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来完成这项任务。
答案 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