5

我需要设计一个“任务管理器”表结构,其中任务可以依赖于其他任务。例如我可以有以下任务:

TASK A: independent
TASK B: independent
TASK C: can not start before TASK B is finished
TASK D: independenet
TESK E: can not start before TASK C and TASK E are finished

每个任务都有标准属性(started_by、assigned_to、due_date、description、status)。我想要一个表结构,让我可以轻松地进行此查询:

  1. 选择所有用户打开的任务,但只选择那些已经可以启动的(意思是上面场景中的任务C和E在依赖任务完成之前不能在这里选择)。

目前我的解决方案是有 2 张桌子:

  • 任务:保存任务记录的表
  • task_dependencies:保存任务到任务依赖关系的表(id、task_id、dependent_task_id)

我对上述场景的当前查询和我当前的表结构如下所示:

SELECT description, from_unixtime( date_due )
FROM tasks
WHERE 
   assigned_user_id = 751
  AND status_id = 'Q'
  AND id NOT
  IN (
    SELECT TD.task_id
    FROM task_dependencies TD
    INNER JOIN tasks T ON TD.dependent_task_id = T.id
    AND T.status_id = 'Q') 
  ORDER BY date_due

  -- status 'Q' = new uncompleted task

这让我得到了正确的结果,但这是正确的方法还是我应该做出更好的表结构和/或查询?

这也是上述场景的SQL 小提琴

4

1 回答 1

3

不知道为什么这么久都没有答案。你所建议的绝对是正确的方式 -taskstask_dependencies. 它已经正确规范化,并允许您在一个查询中选择所需的信息,并在正确的列上建立索引。

小建议:

  • 查询没有错,但最好避免使用 all-dep-task-selecting 子查询并将其设置为:

    SELECT T.description, from_unixtime( T.date_due )
    FROM tasks T
    LEFT JOIN task_dependencies TD
      ON TD.task_id = T.id
    LEFT JOIN tasks T2
      ON T2.task_id = TD.dependent_task_id
    WHERE
      T.assigned_user_id = 751
      AND T.status_id = 'Q'
      AND (T2.status_id != 'Q' OR T2.status_id IS NULL)
    ORDER BY T.date_due
    

    应该优化得更好。(我假设我的查询中有一些错误,无法 sqlfiddle 测试它。但你明白了。)

  • task_dependencies表不需要单独的 PK。您可以做的是对task_id和进行复杂的 PK dep_task_id。尽管拥有单独的 PK 并task_id+dep_task_id作为唯一密钥放置被认为是一种很好的做法。

于 2014-05-06T05:57:11.720 回答