我有一个MySQL数据库,表格如下:
| id | redirect | +-------+----------+ | 1 | NULL | | 2 | 3 | | 3 | NULL | | 4 | 5 | | 5 | 6 | | 6 | 8 | | 7 | NULL | | 8 | NULL | +-------+----------+
我需要为递归解析重定向创建查询。 所以我可以得到结果:
1 1 2 3 3 3 4 8 5 8 6 8 7 7 8 8
由于
答案 0 :(得分:0)
一种方法是获得每个"等级"单独查询。
要获得第一级,我们可以在redirect_id列中测试NULL,以识别"终止"节点
要获得第二级,我们可以使用JOIN操作来匹配具有与"终止"中的id匹配的redirect_id的行。行(先前已确定)。
第三级遵循相同的模式,添加另一个JOIN操作以返回重定向到第二级的行。
等等。
例如:
SELECT t1.id AS start_id
, t1.id AS terminate_id
FROM mytable t1
WHERE t1.redirect_id IS NULL
UNION ALL
SELECT t2.id
, t1.id
FROM mytable t1
JOIN mytable t2 ON t2.redirect_id = t1.id
WHERE t1.redirect_id IS NULL
UNION ALL
SELECT t3.id
, t1.id
FROM mytable t1
JOIN mytable t2 ON t2.redirect_id = t1.id
JOIN mytable t3 ON t3.redirect_id = t2.id
WHERE t1.redirect_id IS NULL
UNION ALL
SELECT t4.id
, t1.id
FROM mytable t1
JOIN mytable t2 ON t2.redirect_id = t1.id
JOIN mytable t3 ON t3.redirect_id = t2.id
JOIN mytable t4 ON t4.redirect_id = t3.id
WHERE t1.redirect_id IS NULL
这种单一查询UNION ALL
方法的局限性在于它需要扩展到有限的最大级别数。 (这种方法不是真正的"递归"。)
如果我们需要一个真正的递归方法,我们可以单独运行每个查询,只需添加额外的"级别"对于每次运行,遵循相同的模式。我们知道,当查询结果没有返回任何行时,我们会耗尽所有可能的路径。
我已经演示了如何使用UNION ALL
运算符将结果合并到一个集合中,使用单个查询。 (如果行的顺序很重要,则在语句末尾添加ORDER BY
子句。在结果集中包含文字" level"列也很容易,例如{{1对于第一个SELECT,第二个查询的1 AS level
等,以确定节点离终止的距离。
MySQL不支持Oracle样式2
语法(在Oracle中,我们可以编写一个遍历此集合并返回指定行的单个查询,任意数量的级别。)
获得真正的"递归" MySQL中的方法需要多次查询。 (请注意,如果服务器配置为允许,则MySQL可以支持"递归"在存储过程调用中。)