MySQL分层递归查询以获取数据

时间:2019-09-15 16:21:33

标签: mysql sql

考虑这是我的表结构。...

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! 接受答案几乎可以解决我的问题,但是只有在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))

3 个答案:

答案 0 :(得分:1)

您可以创建一个将遍历树的存储函数:

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

答案 1 :(得分:0)

您可以通过反转查询中的内容来修改查询中的链接

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))

Demo

答案 2 :(得分:-2)

在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 <>小提琴。