如何解决SQL id链?

时间:2014-07-03 17:55:47

标签: mysql sql

我有一个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

由于

1 个答案:

答案 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可以支持"递归"在存储过程调用中。)