CTE 是处理两个表递归的正确方法吗?
Is CTE the correct way to handle recursion with two tables?
我在下面设置了一个查询,但我在使用递归部分时遇到了问题。我从 Table1 的合同 Abc 和 Xyz 开始。我取 Table1.Id, groupNo 并在 Table2 中查找它们,以在那里获取合同,然后在 Table1 中查找这些合同,重复该过程直到最终returns null,并捕获最后一次迭代。 CTE 是处理这个问题的方法吗?如果是这样,有人可以帮助完成最后一次迭代。我试过嵌套,但没成功。
Table结构
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
这是一种方法。
基本上,我记录每次递归的级别,只保留最高级别。请参阅 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);
我还在第二个 select 中添加了 table2。您希望它表现得像第一个一样,它需要从 table2 中获取分包合同名称。
我在下面设置了一个查询,但我在使用递归部分时遇到了问题。我从 Table1 的合同 Abc 和 Xyz 开始。我取 Table1.Id, groupNo 并在 Table2 中查找它们,以在那里获取合同,然后在 Table1 中查找这些合同,重复该过程直到最终returns null,并捕获最后一次迭代。 CTE 是处理这个问题的方法吗?如果是这样,有人可以帮助完成最后一次迭代。我试过嵌套,但没成功。
Table结构
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
这是一种方法。 基本上,我记录每次递归的级别,只保留最高级别。请参阅 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);
我还在第二个 select 中添加了 table2。您希望它表现得像第一个一样,它需要从 table2 中获取分包合同名称。