如何创建非自引用MySQL递归查询
这里有一个相关的问题: 我试图确定如何在mysql(版本>=8)中创建递归查询,该查询可以收集以某种方式“链接”到原始行的所有行。结构相对简单:如何创建非自引用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
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;