假设这是我的表结构……
id | name | parent_id
19 | category1 | 0
20 | category2 | 19
21 | category3 | 20
22 | category4 | 21
......
现在,我想用一个mysql查询来获取以前相关的行。如果我给出`id=22‘,那么查询应该返回id 21,20,19。
还需要获取(它可以是一个单独的查询)级别的数据返回。也就是说,如果我给出id=22,那么查询应该只返回id 21 (第一级)。id 21,20 (第二级)...
这里有一个类似的link!Accept answer几乎可以解决我的问题,但它只有在parent_id < id
时才能正常工作。
接受答案的一部分:
select id,
name,
parent_id
from (select * from products
order by parent_id, id) products_sorted,
(select @pv := '19') initialisation
where find_in_set(parent_id, @pv)
and length(@pv := concat(@pv, ',', id))
发布于 2019-09-15 17:06:46
您可以创建一个遍历树的存储函数:
delimiter //
create function product_ancestors(in_id int) returns text reads sql data
begin
declare current_id int default in_id;
declare ancestor_ids text default null;
while (current_id <> 0) do
set current_id = (
select parent_id
from products
where id = current_id
);
if (current_id <> 0)
then set ancestor_ids = concat_ws(',', ancestor_ids, current_id);
end if;
end while;
return ancestor_ids;
end //
delimiter ;
将其与
select product_ancestors(22);
这将返回一个逗号分隔的字符串'21,20,19'
。
请参阅demo
发布于 2019-09-15 16:52:06
您可以通过颠倒问题中的链接来调整查询
select id,
name,
parent_id, @pv
from (select * from products
order by id desc) products_sorted,
(select @pv := '21') initialisation
where find_in_set(id, @pv)
and length(@pv := concat(@pv, ',', parent_id))
发布于 2019-09-15 16:30:29
在MySQL 8+中,您可以使用递归CTE:
with recursive cte as (
select c.id, c.parent_id
from categories c
where c.id = 22
union all
select cte.id, c.parent_id
from cte join
categories c
on c.id = cte.parent_id
)
select *
from cte;
如果您也需要的话,可以使用join
来引入名称。
Here是一个db<>fiddle。
https://stackoverflow.com/questions/57945999
复制