我试图编写一个递归的SELECT查询来查看存储在数据库中的图形(MariaDB 10.2.6)。我的图表的节点标有两个坐标 - 让他们称之为x和y。构造图形使得在(x,y)和(x-1,y),(x,y-1)和(x-1,y-1)之间存在边缘。然后通过函数对每个边进行排序,该函数取决于与每个节点相关联的值的差异(例如,f(n1,n2)= n2.value-n1.value,其中n1和n2是共享边的两个节点)。 / p>
为了使这更复杂,假设边缘函数对于(x,y) - >的情况是不同的。 (x-1,y)比其他情况。为这种情况调用函数f1,对于其他情况调用f2。
我想要做的是根据以下规则从任意起点遍历此图:
现在我正尝试使用递归SELECT查询,如下所示:
WITH RECURSIVE step (
id, -- step number
tid, -- substep number
nid, -- node id
x, -- node x
y, -- node y
f -- value of f between the previous and current nodes
)
AS
(
-- Initial step.
SELECT 1 AS id, 1 AS tid, n1.id AS nid, n1.x, n1.y, 0.0 AS f
FROM nodes AS n1 WHERE n1.x = initial_x AND n1.y = initial_y
-- Begin the recursive part.
UNION ALL
-- Use a subquery here so we can limit each step.
SELECT * FROM (
-- First part of the subquery checks (x-1,y).
SELECT step.id + 1 AS id, 1 AS tid, n2.id AS nid,
n2.x, n2.y, f1(v1.value, v2.value) AS f
FROM step
INNER JOIN values v1 ON v1.node = step.nid
INNER JOIN nodes n2 ON (n2.x = step.x - 1 AND n2.y = step.y)
INNER JOIN values v2 ON v2.node = n2.id
WHERE f < some_cutoff
-- Second part of the subquery checks (x,y-1) and (x-1,y-1).
UNION
SELECT step.id + 1 AS id, 2 AS tid, n2.id AS nid,
n2.x, n2.y, f2(v1.value, v2.value) AS f
FROM step
INNER JOIN values v1 ON v1.node = step.nid
INNER JOIN nodes n2 ON (n2.x = step.x AND n2.y = step.y - 1)
OR (n2.x = step.x - 1 AND n2.y = step.y - 1)
INNER JOIN values v2 ON v2.node = n2.id
-- Third part again selects (x-1,y) but without cutoff condition.
UNION
SELECT step.id + 1 AS id, 3 AS tid, n2.id AS nid,
n2.x, n2.y, f1(v1.value, v2.value) AS f
FROM step
INNER JOIN values v1 ON v1.node = step.nid
INNER JOIN nodes n2 ON n2.x = step.x - 1 AND n1.y = step.y
INNER JOIN values v2 ON v2.node = n2.id
) a -- give the subquery a dummy name
-- At the end of the recursive step, sort and take the first step.
ORDER BY tid, f ASC LIMIT 1
)
-- Get the list of steps.
SELECT * FROM step ORDER BY id ASC;
我的想法基本上是将三个条件分成三个联合子查询,每个子查询的等级(tid)都在增加。在每个递归步骤结束时,我按此等级排序,然后按每个等级中的f值排序。这应该给我留下一组行,最优选的节点位于顶部。最后,我使用LIMIT 1来选择最有利的节点,并继续递归。当我到达没有合适邻居的节点(x_min,y_min)时,子查询应该返回一个空集,并且递归应该终止。
不幸的是,这个查询现在对我不起作用。每当我尝试执行它时,MariaDB都会挂起,我不知道为什么。我明显的第一个想法是递归永远不会终止(无限循环),但我相信在减少的x和y上的INNER JOIN应该阻止这种情况。我错过了一些重要的事情/不了解如何正确使用递归查询?有没有更好的方法来解决这类问题?