SQL 查询 parent child 没有关系

SQL query for parent child with no relationship

我需要有关我要创建的查询的帮助。例如,假设我有这个 table:

Description                     Level     Is_Active
----------------------------------------------------
 (1)Metallic industry products        1          1
 (2)+ Various metal products          2          1
 (3)++  Other metal products          3          1
 (1)Rubber and plastic products       1          1
 (2)+ Rubber products                 2          1
 (2)+ Other rubber products           2          1
 (3)++  Other product types           3          1

其中级别指定关系。 table 中的记录被设置为再现树结构。我想要做的是一个查询,其中 selects 所有 parents 和 children 从这个 table 是活跃的。例如,如果金属工业产品的 Is_Active 列设置为 0,我不想显示它,它是 children(各种金属产品和其他金属产品)。

各种金属制品也一样,没激活的就不显示了,就是children。我尝试使用相同的 table 或使用 WITH 函数加入,但遗憾的是我找不到解决方案。

一个更具体的例子是这样的。金属工业产品变得不活跃。那么 select 结果应该是:

Description                     Level     Is_Active
----------------------------------------------------
 (1)Rubber and plastic products       1          1
 (2)+ Rubber products                 2          1
 (2)+ Other rubber products           2          1
 (3)++  Other product types           3          1

或者假设金属行业产品的 child 变为非活动状态。结果集应该是这样的:

Description                     Level     Is_Active
----------------------------------------------------
 (1)Metallic industry products        1          1
 (1)Rubber and plastic products       1          1
 (2)+ Rubber products                 2          1
 (2)+ Other rubber products           2          1
 (3)++  Other product types           3          1

好吧,我已经试过了,它不是很漂亮,但看看你的想法。我使用 WHILE 循环而不是游标来最小化代码:

  create table #ordered_products
(id int identity(1,1),
 grouping int default 0,
 Description varchar(128),
 level int,
 is_active bit);

 insert into #ordered_products (Description, level, is_active)
 select description, level, is_active from products;

-- All rows now have an order

declare @grouping int = 0;
declare @currentid int;
declare @found bit = 1;
declare @level int;
declare @base int;

set @currentid = (select min(id) from #ordered_products);

-- Go through all the rows setting a new group each time we hit level 1

while (@found = 1)
begin
  set @level = (select level from #ordered_products where id = @currentid);

  if (@level = 1)
  begin
    set @grouping = @grouping + 1
  end

  update #ordered_products set grouping = @grouping where id = @currentid

  set @currentid = @currentid + 1;
  set @found = (select 1 from #ordered_products where id = @currentid);

end

-- For each group, set the children to be inactive if the parent is

declare @maxgroup int = (select MAX(GROUPING) from #ordered_products);

declare @currentgroup int = 1;

while (@currentgroup <= @maxgroup)
begin

    begin
        set @base = (select MIN(id) from #ordered_products where is_active = 0 and grouping = @currentgroup);

        if (@base > 0)
        begin
            update #ordered_products set is_active = 0 where grouping = @currentgroup and id > @base;
        end
    end 

    set @currentgroup = @currentgroup + 1;  
end 

-- Output

select * from #ordered_products where is_active = 1;

drop table #ordered_products;