如何为项目管理任务记录的顺序跟踪编写递归MySQL查询

如何为项目管理任务记录的顺序跟踪编写递归MySQL查询,mysql,sql,stored-procedures,project-management,recursive-query,Mysql,Sql,Stored Procedures,Project Management,Recursive Query,我正在尝试重构一个项目管理系统,我想帮助编写一个递归MySQL查询,以顺序跟踪项目中的所有任务。我认为它很可能需要一个存储过程 考虑两个项目: 里程碑A至里程碑F-10任务(见项目图表说明): 里程碑U至里程碑W-6任务(见项目图表说明): 将这些项目实施到两个MySQL表中——proj和proj_task,表proj列出了所有16个项目任务,而proj_task表描述了每个任务在id_父字段中列出父任务,在id_子字段中列出子任务的关系: CREATE TABLE IF NOT EXIST

我正在尝试重构一个项目管理系统,我想帮助编写一个递归MySQL查询,以顺序跟踪项目中的所有任务。我认为它很可能需要一个存储过程

考虑两个项目:

里程碑A至里程碑F-10任务(见项目图表说明):

里程碑U至里程碑W-6任务(见项目图表说明):

将这些项目实施到两个MySQL表中——
proj
proj_task
,表
proj
列出了所有16个项目任务,而
proj_task
表描述了每个任务在id_父字段中列出父任务,在id_子字段中列出子任务的关系:

CREATE TABLE IF NOT EXISTS `proj` (
  `id` int(13) NOT NULL AUTO_INCREMENT,
  `project_task_event` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

INSERT INTO `proj` (`id`, `project_task_event`) VALUES
(1, 'Task A'),
(2, 'Task B'),
(3, 'Task C'),
(4, 'Task D'),
(5, 'Task E'),
(6, 'Task F'),
(7, 'Task G'),
(8, 'Task H'),
(9, 'Task I'),
(10, 'Task J'),
(11, 'Task U'),
(12, 'Task V'),
(13, 'Task W'),
(14, 'Task X'),
(15, 'Task Y'),
(16, 'Task Z');

CREATE TABLE IF NOT EXISTS `proj_task` (
  `id` int(13) NOT NULL AUTO_INCREMENT,
  `id_parent` int(13) NOT NULL,
  `id_child` int(13) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id_parent` (`id_parent`,`id_child`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

INSERT INTO `proj_task` (`id`, `id_parent`, `id_child`) VALUES
(1, 0, 1),
(2, 1, 2),
(3, 2, 3),
(4, 2, 4),
(5, 3, 5),
(6, 4, 5),
(7, 5, 6),
(8, 1, 7),
(9, 1, 8),
(10, 7, 9),
(11, 8, 9),
(12, 9, 10),
(13, 10, 6),
(14, 0, 11),
(15, 11, 12),
(16, 12, 13),
(17, 11, 14),
(18, 14, 15),
(19, 15, 13),
(20, 11, 16),
(21, 16, 13);
两个任务A和U没有父任务(id_parent=0),因此根据定义,它们各自定义了一个新项目:

select p.`project_task_event` as 'Projects' from `proj` p, `proj_task` t where p.id = t.`id_child` and t.`id_parent` = 0;
+----------+
| Projects |
+----------+
| Task A   |
| Task U   |
+----------+
有人能帮我写一个递归的MySQL查询来选择项目的每个任务(下面的输出示例),只使用上面的表吗?我要查找的确切输出是列出项目任务(
proj
project\u task\u event
),它们是给定项目开始父级的子后代(其中
proj\u task
=0)。父级可以通过其唯一的
proj
id
或其唯一的
proj\u任务
id
引用

+---------------+
| Project Tasks |
+---------------+
| Task A        |
| Task B        |
| Task C        |
| Task D        |
| Task E        |
| Task F        |
| Task G        |
| Task H        |
| Task I        |
| Task J        |
+---------------+

+---------------+
| Project Tasks |
+---------------+
| Task U        |
| Task V        |
| Task W        |
| Task X        |
| Task Y        |
| Task Z        |
+---------------+
目前,系统在
proj
表中有一个额外的字段,这使得上述SELECT查询变得微不足道,但我想删除该字段,因为所有必要的数据似乎都存在于递归查询中:

CREATE TABLE IF NOT EXISTS `proj` (
  `id` int(13) NOT NULL AUTO_INCREMENT,
  `project_task_event` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
  `proj_id` int(13) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `proj_id` (`proj_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

INSERT INTO `proj` (`id`, `project_task_event`, `proj_id`) VALUES
(1, 'Task A', 1),
(2, 'Task B', 1),
(3, 'Task C', 1),
(4, 'Task D', 1),
(5, 'Task E', 1),
(6, 'Task F', 1),
(7, 'Task G', 1),
(8, 'Task H', 1),
(9, 'Task I', 1),
(10, 'Task J', 1),
(11, 'Task U', 11),
(12, 'Task V', 11),
(13, 'Task W', 11),
(14, 'Task X', 11),
(15, 'Task Y', 11),
(16, 'Task Z', 11);

select `project_task_event` as 'Project Tasks' from `proj` where `proj_id` = 1;
+---------------+
| Project Tasks |
+---------------+
| Task A        |
| Task B        |
| Task C        |
| Task D        |
| Task E        |
| Task F        |
| Task G        |
| Task H        |
| Task I        |
| Task J        |
+---------------+

select `project_task_event` as 'Project Tasks' from `proj` where `proj_id` = 11;
+---------------+
| Project Tasks |
+---------------+
| Task U        |
| Task V        |
| Task W        |
| Task X        |
| Task Y        |
| Task Z        |
+---------------+
看看这个:

   select DISTINCT a.id,a.project_task_event,a.proj_id,a.id_parent,a.id_child,b.project_task_event from 
(select a.id,project_task_event,proj_id,id_parent,id_child from 
(select id,project_task_event,proj_id from proj) as a
left JOIN
(select id,id_parent,id_child from proj_task)as b
on a.id = b.id_parent) as a

left JOIN


(select a.id,project_task_event,proj_id,id_parent,id_child from 
(select id,project_task_event,proj_id from proj) as a
left JOIN
(select id,id_parent,id_child from proj_task)as b
on a.id = b.id_parent)as b
on a.id_child = b.id
结果是:

这是给定的示例:

对于具有任意复杂性的项目,您不能使用单一查询执行此操作。MySQL不提供递归查询(请参阅其他地方如何实现)。部分解决方案是使用for mysql,但是我发现它有点有限,很难在查询中与其他数据集集成

我建议最好的解决方案是使用过程/函数填充临时表。在伪代码中

 Create temptable (
      Node integer primary key,
      Gen integer);

Set generation=0;

Insert into temptable (node, gen) values (starting_node, generation);

Do
    Insert ignore into temptable (node, gen)
    Select child_id, generation+1
    From  temptable tt
    Inner join proj_tasks pj
       On tt.node=pj.parent_id
    Where tt.gen=generation;

    If 0 rows inserted or generation ≥ max_iterations break;

    Set generation = generation+1;
 Repeat;

 Select * from temptable;

您需要的确切输出是什么?需要在表格中明确吗?我们只处理两个表吗?proj和proj_任务表?id_父项和id_子项来自哪里?我的意思是它的值从哪里来?你的意思是所有这些都取决于id\u parent和id\u child?我认为我不熟悉一个模型,在这个模型中,给定实体的父级和子级都被存储。它有名字吗?这个结果返回到第一个插图,如下所示。只是想让你检查一下。你的优雅解决方案非常接近,显示了所有项目中的所有任务。非常感谢。如上所述,我希望在不使用
proj
proj\u id
字段的情况下重构它。当我简单地从查询中删除
proj
proj\u id
字段时,我们仍然会得到相同的正确结果,显示所有项目中的所有任务。我给出的示例显示了2个项目,但在生产中,表可能包含许多项目的数据。如果任务A的
proj
id
=1,我们如何约束查询只显示第一个项目中的那些任务?或者,如果任务U的
proj
id
=11,则约束查询仅显示来自第二个项目的任务?这意味着您需要根据项目id获取所有任务?