CTE是使用两个表处理递归的正确方法吗?

时间:2015-09-03 12:03:02

标签: sql-server tsql common-table-expression

我在下面有一个查询设置,我在使用递归片时遇到了麻烦。我从表1中的合同,Abc和Xyz开始。我使用Table1.Id,groupNo并在Table2中查找它们以获得那些合同,然后在Table1中查看这些合同,重复该过程,直到它最终返回null,并捕获最后一次迭代。 CTE是解决这个问题的方法吗?如果是这样,有人可以帮助完成最后一次迭代。我尝试过筑巢,并且没有让它起作用。

表结构

create table Table1 (id int, groupNo int, contract varchar(3))
insert into Table1 values(33,2,'Abc')
insert into Table1 values(34,8,'Xyz')
insert into Table1 values(88,11,'123')
insert into Table1 values(89,11,'456')

create table Table2 (id int, groupNo int, contract varchar(3))
insert into Table2 values(34,8,'123')
insert into Table2 values(34,8,'456')
insert into Table2 values(89,11,'789')

查询

with myCTE (id,groupNo,contract) as
(
    select 
        t1.id
        ,t1.groupNo
        ,t2.contract 
    from Table1 t1
        inner join Table2 t2 on t1.id = t2.id and t1.groupNo = t2.groupNo
    union all
    select
        t1.id
        ,t1.groupNo
        ,c2.contract
    from myCTE c2
        inner join Table1 t1 on c2.contract = t1.contract
)

select top 10 id, groupNo, contract
from myCTE

SQL FIDDLE

1 个答案:

答案 0 :(得分:1)

这是一种做法。 基本上,我记录每个递归的级别,只保持最高级别。请参阅SQL Fiddle并在下面查询:

declare @Table1 table(id int, groupNo int, contract varchar(3));
insert into @Table1 values(33,2,'Abc');
insert into @Table1 values(34,8,'Xyz');
insert into @Table1 values(88,11,'123');
insert into @Table1 values(89,11,'456');

declare @Table2 table(id int, groupNo int, contract varchar(3));
insert into @Table2 values(34,8,'123');
insert into @Table2 values(34,8,'456');
insert into @Table2 values(89,11,'789');



with myCTE (level, id, groupNo, contract, subcontract) as
(
    select 0, t1.id,t1.groupNo, t1.contract
        ,t2.contract 
    from @Table1 t1
        inner join @Table2 t2 on t1.id = t2.id and t1.groupNo = t2.groupNo
    union all
    select level+1, c2.id, c2.groupNo, c2.contract
        ,t2.contract
    from myCTE c2
        inner join @Table1 t1 on c2.subcontract = t1.contract
        inner join @Table2 t2 on t1.id = t2.id and t1.groupNo = t2.groupNo
)
Select c.* From myCTE as c
Inner join (select id, groupNo, contract, level = max(level) From myCTE Group by id, groupNo, contract) as m 
    On m.level = c.level and m.id = c.id and m.groupNo = c.groupNo and m.contract = c.contract
OPTION (MAXRECURSION 0);

我还将table2添加到第二个选择中。您希望它的行为与第一个相同,并且需要从table2获取转包名称。