使用内部联接进行递归选择

时间:2014-05-29 09:57:15

标签: sql tsql

所以我正在尝试编写一个递归查询来获取项目及其父项。问题是我的结构可以有很多父母,查询没有得到最后一行。结构是:

Entity

Id |
1  |
2  |
3  |


EntityMembership

ChildId | ParentId
3       | 2
2       | 1

到目前为止,查询看起来像:

with results(BaseId, Id, ParentId) as
(
 select e.id as BaseId, e.id, em.parentid
 from entity e
 left join EntityMembership em on e.Id = em.ChildID
 union all
 select r.BaseId, e.id, em.parentid
 from entity e
 inner join EntityMembership em on e.Id = em.ChildID
 inner join results r on r.parentid = e.id
 where r.Id<> r.ParentId
)
select results.Id
from results
where BaseId = 3

出现如下:

3 |
2 |

显然内部联接阻止“1”出现在结果中,因为它没有父级,但我不知道如何重写它以包含它。

1 个答案:

答案 0 :(得分:1)

问题是你在CTE的第二部分对EntityMembership进行了内部联接,所以你在结果中没有得到“1”。它应该是外连接(如第一部分中所示),但不允许在递归CTE中具有外连接。我的解决方案是提前在另一个CTE中加入Entity和EntityMembership,并在递归中使用它。

with joined(ChildId, ParentId) as
(select e.id, em.parentid
 from entity e 
 left outer join entitymembership em on em.childid = e.id
 ), 
 results(BaseId, Id, ParentId) as
(
 select j.ChildId as BaseId, j.ChildId, j.parentid
 from joined j 
 union all
 select r.BaseId, j.ChildId, j.parentid
 from joined j
 inner join results r on r.parentid = j.ChildId
 where r.Id <> r.ParentId
)

select Id
from results
where BaseId = 3

这是一种稍微不同的编写方式,过滤CTE中的子Id,而不是之后:

with joined(ChildId, ParentId) as
(select e.id, em.parentid
 from entity e 
 left outer join entitymembership em on em.childid = e.id
 )
,results(ChildId, ParentId) as
(
 select j.childid, j.parentid
 from joined j
 where j.childid = 3
 union all
 select j.childid, j.parentid
 from joined j
 join results r on r.parentid = j.childid 
)


select ChildId
from results