MySQL8 查询一个等级的全血统(祖先+后代)
MySQL8 query whole bloodline (ancestors + descendants) of a hierarchy
MySQL8 允许使用 with
语法来查询层次结构。例如,查询一个项目的所有祖先。反过来也可以递归查询所有后代。
我正在寻找结合了这两个方面的查询:所有后代、祖先的查询,最好是项目自身(请参阅包含的图形,所有彩色项目)。其实也可以说,无所有祖先兄弟姐妹的所有物品。我想我们可以说“血统”。可以只 union
这两个结果,但我需要一个没有联合的解决方案。
这可能吗?我欢迎任何方法。
作为一个概览,我的工会尝试。注意,目前有一个错误,有些 parent_id 是错误的;我正在努力)
(with recursive cte as (
SELECT id, parent_id
from categories
where id = 'C2'
union all
select t.parent_id, cte.id
from cte
inner join categories t on t.id = cte.parent_id
where cte.id is not null
)
select id, parent_id
from cte
where cte.id is not null)
union
(with recursive cte as (
SELECT id, parent_id
from categories
where id = 'C2'
union all
select t.id, cte.parent_id
from cte
inner join categories t on t.parent_id = cte.id
)
select id, parent_id
from cte);
以及给定图表的数据。
INSERT INTO categories (id, parent_id) VALUES ('A1', null);
INSERT INTO categories (id, parent_id) VALUES ('B1', 'A1');
INSERT INTO categories (id, parent_id) VALUES ('B2', 'A1');
INSERT INTO categories (id, parent_id) VALUES ('B3', 'A1');
INSERT INTO categories (id, parent_id) VALUES ('C1', 'B2');
INSERT INTO categories (id, parent_id) VALUES ('C2', 'B2');
INSERT INTO categories (id, parent_id) VALUES ('D1', 'C1');
INSERT INTO categories (id, parent_id) VALUES ('D2', 'C1');
INSERT INTO categories (id, parent_id) VALUES ('D3', 'C2');
INSERT INTO categories (id, parent_id) VALUES ('D4', 'C2');
INSERT INTO categories (id, parent_id) VALUES ('D5', 'C2');
INSERT INTO categories (id, parent_id) VALUES ('E1', 'D5');
预期输出
id,parent_id
C2,B2
A1,null
B2,A1
D3,C2
D4,C2
D5,C2
E1,D5
如果您在 ON 子句中包含祖先和后代的两个条件,则可以使用 1 个递归 CTE 来完成。
您将需要另一列 type
,它指示每一行是针对祖先还是后代:
WITH RECURSIVE cte AS (
SELECT id, parent_id, 0 type
FROM categories
WHERE id = 'C2'
UNION ALL
SELECT t.id, t.parent_id,
CASE WHEN c.parent_id = t.id THEN -1 ELSE 1 END
FROM categories t INNER JOIN cte c
ON c.parent_id = t.id OR c.id = t.parent_id
WHERE (type = 0)
OR (c.parent_id = t.id AND type = -1)
OR (c.id = t.parent_id AND type = 1)
)
SELECT id, parent_id FROM cte
参见demo。
MySQL8 允许使用 with
语法来查询层次结构。例如,查询一个项目的所有祖先。反过来也可以递归查询所有后代。
我正在寻找结合了这两个方面的查询:所有后代、祖先的查询,最好是项目自身(请参阅包含的图形,所有彩色项目)。其实也可以说,无所有祖先兄弟姐妹的所有物品。我想我们可以说“血统”。可以只 union
这两个结果,但我需要一个没有联合的解决方案。
这可能吗?我欢迎任何方法。
作为一个概览,我的工会尝试。注意,目前有一个错误,有些 parent_id 是错误的;我正在努力)
(with recursive cte as (
SELECT id, parent_id
from categories
where id = 'C2'
union all
select t.parent_id, cte.id
from cte
inner join categories t on t.id = cte.parent_id
where cte.id is not null
)
select id, parent_id
from cte
where cte.id is not null)
union
(with recursive cte as (
SELECT id, parent_id
from categories
where id = 'C2'
union all
select t.id, cte.parent_id
from cte
inner join categories t on t.parent_id = cte.id
)
select id, parent_id
from cte);
以及给定图表的数据。
INSERT INTO categories (id, parent_id) VALUES ('A1', null);
INSERT INTO categories (id, parent_id) VALUES ('B1', 'A1');
INSERT INTO categories (id, parent_id) VALUES ('B2', 'A1');
INSERT INTO categories (id, parent_id) VALUES ('B3', 'A1');
INSERT INTO categories (id, parent_id) VALUES ('C1', 'B2');
INSERT INTO categories (id, parent_id) VALUES ('C2', 'B2');
INSERT INTO categories (id, parent_id) VALUES ('D1', 'C1');
INSERT INTO categories (id, parent_id) VALUES ('D2', 'C1');
INSERT INTO categories (id, parent_id) VALUES ('D3', 'C2');
INSERT INTO categories (id, parent_id) VALUES ('D4', 'C2');
INSERT INTO categories (id, parent_id) VALUES ('D5', 'C2');
INSERT INTO categories (id, parent_id) VALUES ('E1', 'D5');
预期输出
id,parent_id
C2,B2
A1,null
B2,A1
D3,C2
D4,C2
D5,C2
E1,D5
如果您在 ON 子句中包含祖先和后代的两个条件,则可以使用 1 个递归 CTE 来完成。
您将需要另一列 type
,它指示每一行是针对祖先还是后代:
WITH RECURSIVE cte AS (
SELECT id, parent_id, 0 type
FROM categories
WHERE id = 'C2'
UNION ALL
SELECT t.id, t.parent_id,
CASE WHEN c.parent_id = t.id THEN -1 ELSE 1 END
FROM categories t INNER JOIN cte c
ON c.parent_id = t.id OR c.id = t.parent_id
WHERE (type = 0)
OR (c.parent_id = t.id AND type = -1)
OR (c.id = t.parent_id AND type = 1)
)
SELECT id, parent_id FROM cte
参见demo。