Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建非自引用MySQL递归查询_Mysql_Sql_Recursive Query - Fatal编程技术网

如何创建非自引用MySQL递归查询

如何创建非自引用MySQL递归查询,mysql,sql,recursive-query,Mysql,Sql,Recursive Query,这里有一个相关的问题: 我试图确定如何在mysql(版本>=8)中创建递归查询,该查询可以收集以某种方式“链接”到原始行的所有行。结构相对简单: CREATE TABLE link ( id INT, left_id INT, right_id INT ); CREATE TABLE item ( id INT, content VARCHAR(100) ); INSERT INTO item (id, content) VALUES (1, 'first linked

这里有一个相关的问题:

我试图确定如何在mysql(版本>=8)中创建递归查询,该查询可以收集以某种方式“链接”到原始行的所有行。结构相对简单:

CREATE TABLE link (
  id INT,
  left_id INT,
  right_id INT
);

CREATE TABLE item (
  id INT,
  content VARCHAR(100)
);

INSERT INTO item (id, content) VALUES (1, 'first linked item');
INSERT INTO item (id, content) VALUES (2, 'unlinked item');
INSERT INTO item (id, content) VALUES (3, 'second linked item');
INSERT INTO item (id, content) VALUES (4, 'third linked item');
INSERT INTO item (id, content) VALUES (5, 'fourth linked item');
INSERT INTO item (id, content) VALUES (6, 'second group item 1');
INSERT INTO item (id, content) VALUES (7, 'second group item 2');

INSERT INTO link (id, left_id, right_id) VALUES (1, 1, 3);
INSERT INTO link (id, left_id, right_id) VALUES (2, 4, 3);
INSERT INTO link (id, left_id, right_id) VALUES (2, 5, 1);
INSERT INTO link (id, left_id, right_id) VALUES (4, 6, 7);
在这里,我们创建了许多“item”行。稍后,我们可以通过向“link”表中添加一行来决定将一个项目任意链接到另一个项目。“left_id”和“right_id”只是一个项目和另一个项目的id。这意味着一个链接是用一个项目作为左项还是右项来完成没有区别

查询应该从指定的一个或多个项目开始,查找具有匹配的left\u id或right\u id的链接,并将项目添加到结果中,然后对于这些新行,检查更多链接等,直到没有剩余链接

对于上面提供的测试数据,我希望:

Calling query with condition "content = 'first linked item'":
Result: 
1 | 'first linked item'
3 | 'second linked item'
4 | 'third linked item'
5 | 'fourth linked item'

mysql 8+中有哪些工具可以有效地调用此类查询

您可以使用递归CTE遍历图形。例如:

with
recursive i as (
  select id, content, -1 as source 
  from item where content = 'first linked item'
 union all
  select m.id, m.content, i.id
  from i
  join link l on l.left_id = i.id or l.right_id = i.id
  join item m on m.id <> i.id and m.id <> i.source and m.id = l.left_id
              or m.id <> i.id and m.id <> i.source and m.id = l.right_id
)
select id, content from i;

看看我在哪里介绍了循环。

欣赏起点。但是,我尝试在未修改的示例上运行此命令:——即使仅使用第一行链接,它也超出了递归深度。修复了它。请注意,只要没有循环,它就会工作。谢谢,我认为它是相当自我记录的。然而,无周期要求可能是调试可用性的噩梦,因为一个错误的插入可能会导致大量超时。我不相信会有一个索引的方法。有没有任何机制可以建立一个链接ID列表,这样就不会有链接被访问两次?@Rboreal\u Frippery查看新的解决方案。
with
recursive i as (
  select id, content, -1 as source 
  from item where content = 'first linked item'
 union all
  select m.id, m.content, i.id
  from i
  join link l on l.left_id = i.id or l.right_id = i.id
  join item m on m.id <> i.id and m.id <> i.source and m.id = l.left_id
              or m.id <> i.id and m.id <> i.source and m.id = l.right_id
)
select id, content from i;
with
recursive i as (
  select id, content, concat(',', id, ',') as route 
  from item where content = 'first linked item'
 union all
  select m.id, m.content, concat(i.route, m.id, ',')
  from i
  join link l on l.left_id = i.id or l.right_id = i.id
  join item m on i.route not like concat('%,', m.id, ',%')
    and (m.id = l.left_id or m.id = l.right_id)
)
select distinct id, content from i;