我需要设计一个“任务管理器”表结构,其中任务可以依赖于其他任务。例如,我可以执行以下任务:
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)。我想要一个可以让我轻松执行此查询的表结构:
- 选择所有用户的打开任务,但只选择那些已经可以开始的(意味着在上面的场景中,在依赖任务完成之前不能在这里选择任务 C 和 E)。
目前我的解决方案是有 2 个表:
- tasks:保存任务记录的表
- 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 fiddle对于上述情况。
最佳答案
不知道为什么这么长时间都没有得到答复。你所建议的是绝对正确的方法 - tasks
和 task_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
和dep_task_id
创建一个复杂的 PK。虽然拥有单独的 PK 并将task_id+dep_task_id
作为唯一键被认为是一种很好的做法。
关于具有任务依赖性的任务管理器应用程序的 MySQL 表结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18890218/