Postgresql 在深度搜索样式中选择下一步
博士后12. 我有一张“步骤”表,如: 哪种想法是——必须执行的一些步骤<代码>完成表示该步骤已完成Postgresql 在深度搜索样式中选择下一步,postgresql,Postgresql,博士后12. 我有一张“步骤”表,如: 哪种想法是——必须执行的一些步骤完成表示该步骤已完成after设置执行顺序,并且可以为空(如果为空,则可以按任何顺序运行)。否则,它会指出必须在当前事件之前执行的记录。其数据可能如下所示: id | after | done ----+---------+--------- 1 | NULL | true 2 | 1 | false 3 | 2 | false 4 | NULL | true ...
after
设置执行顺序,并且可以为空(如果为空,则可以按任何顺序运行)。否则,它会指出必须在当前事件之前执行的记录。其数据可能如下所示:
id | after | done
----+---------+---------
1 | NULL | true
2 | 1 | false
3 | 2 | false
4 | NULL | true
...
其中步骤=3应该在步骤=2之后运行,步骤=2在步骤=1之后运行,步骤=1不依赖于任何顺序,而且它已经完成,步骤=4也不依赖于,但它已经完成,这是出于我们的兴趣
我需要选择准备运行的记录的id
。准备就绪的标准是:它应该是尚未完成的步骤,并且它属于最长的“路线”。这也意味着,多个选择必须返回相同“路线”的步骤(这是一个重要的要求),因此我们的想法是在相同(最长的)“路线”上一步一步地“行走”,除非完全完成。然后,下一次选择将返回下一个最长“路由”的下一个未完成步骤,依此类推。类似于深度搜索:你走最长的路线,沿着这条路线走到终点。然后下一条路线
我认为这是递归查询,但我不知道如何编写它
编辑-1:如果某些路线的长度相等,则可以选择其中任何一条路线,但每次都选择相同的路线
EDIT-2:查询完id
后,我计划更新步骤的done
(设置为true),这保证了在路线上“行走”/“移动”
EDIT-3:“多个选择必须返回同一路由的步骤”意味着第一个查询返回最长路由的id(然后我将更新
done
列),之后-第二个查询必须返回同一路由的下一个步骤(它仍然是最长的)。如果有多个最长的路由(例如,2个路由,包含10个步骤),则使用第一个/最后一个路由,下一个查询应返回相同路由的步骤(例如,始终是第一个路由)。要从最长的步骤链中获取撤消的步骤,请执行以下操作:
CREATE TABLE steps (
id integer primary KEY,
after integer REFERENCES steps(id),
done boolean);
INSERT INTO steps
values
(1 , NULL , TRUE),
(2 , 1 , false),
(3 , 2 , false),
(4 , NULL , TRUE);
WITH RECURSIVE routes(id , to_do_first , step_no ) AS (
SELECT id, CASE WHEN done THEN NULL ELSE id END AS to_do_first, 1 AS step_no
FROM steps
WHERE after IS NULL
UNION ALL
SELECT steps.id,
CASE
WHEN routes.to_do_first IS NOT NULL THEN routes.to_do_first
WHEN steps.done THEN NULL
ELSE steps.id
END AS to_do_first,
routes.step_no + 1
FROM steps
JOIN routes ON routes.id = steps.AFTER
)
SELECT
*
FROM
routes
WHERE
to_do_first IS NOT NULL
ORDER BY
step_no DESC
LIMIT 1
关键是选择不需要在之前(之后为null)执行的步骤作为种子,然后添加需要上一次迭代执行的步骤。此外,我还寻求步骤链中未完成的第一步。之后,返回最长但尚未完成的链的最后一步。
to_do_first
是要完成的步骤id。请通过“多个选择必须返回相同“路线”的步骤”解释您遇到的问题。我刚刚添加了编辑3
CREATE TABLE steps (
id integer primary KEY,
after integer REFERENCES steps(id),
done boolean);
INSERT INTO steps
values
(1 , NULL , TRUE),
(2 , 1 , false),
(3 , 2 , false),
(4 , NULL , TRUE);
WITH RECURSIVE routes(id , to_do_first , step_no ) AS (
SELECT id, CASE WHEN done THEN NULL ELSE id END AS to_do_first, 1 AS step_no
FROM steps
WHERE after IS NULL
UNION ALL
SELECT steps.id,
CASE
WHEN routes.to_do_first IS NOT NULL THEN routes.to_do_first
WHEN steps.done THEN NULL
ELSE steps.id
END AS to_do_first,
routes.step_no + 1
FROM steps
JOIN routes ON routes.id = steps.AFTER
)
SELECT
*
FROM
routes
WHERE
to_do_first IS NOT NULL
ORDER BY
step_no DESC
LIMIT 1