如何在查询中使用递归获取父项的所有子项,然后获取其子项

时间:2012-12-13 10:01:17

标签: sql-server-2008 tree recursive-query

我的结构如下:

<Unit>
  <SubUnit1>
           <SubSubUnit1/>
           <SubSubUnit2/>
           ...
           <SubSubUnitN/>
  </SubUnit1/>
  <SubUnit2>
           <SubSubUnit1/>
           <SubSubUnit2/>
           ...
           <SubSubUnitN/>
  </SubUnit2/>
  ...
  <SubUnitN>
           <SubSubUnit1/>
           <SubSubUnit2/>
           ...
           <SubSubUnitN/>
  </SubUnitN/>
</Unit>

这个结构有3个级别:主要单元,SubUnits和SubSubUnits。

我想通过UnitId选择所有孩子 如果我按单位搜索,我必须得到所有树 如果我通过SubUnit1搜索,我必须得到SubUnit1和SubUnit1的所有子项。
如果我搜索SubSubUnit2,我必须得到它自己
这是我的尝试:

with a(id, parentid, name)
as (
select id, parentId, name
   from customer a
   where parentId is null 
union all
   select a.id, a.parentid, a.Name
   from customer
     inner join a on customer.parentId = customer.id
    )
select parentid, id, name 
from customer pod
where pod.parentid in (
select id
from customer grbs
where grbs.parentid in (
select id
from customer t
where t.parentid = @UnitId
))
union 
select parentid, id, name
from customer grbs
where grbs.parentid in (
select id
from customer t
where t.parentid = @UnitId
)
union
select parentid, id, name
from customer c
where c.Id = @UnitId
order by parentid, id

我使用了3个联合词,它不是很好但是有效。案例结构将有N个级别,我必须如何获得正确的结果?

2 个答案:

答案 0 :(得分:28)

DECLARE @Id int = your_UnitId
;WITH cte AS 
 (
  SELECT a.Id, a.parentId, a.name
  FROM customer a
  WHERE Id = @Id
  UNION ALL
  SELECT a.Id, a.parentid, a.Name
  FROM customer a JOIN cte c ON a.parentId = c.id
  )
  SELECT parentId, Id, name
  FROM cte

SQLFiddle上的演示

答案 1 :(得分:2)

如果父代id是其自身的子代,则我们需要使用其他查询。例如,架构结构如下所示

CREATE TABLE customer
(
  id int,
  parentid int,
  name nvarchar(10)
)

INSERT customer
VALUES(1,  1, 'aaa'),
  (2,  1,    'bbb'),
  (3,  2,    'ccc'),
  (4,  2,    'ddd'),
  (5,  1,    'eee'),
  (6,  5,    'fff'),
  (7,  5,    'ggg'),
  (8,  8,    'hhh'),
  (9,  8,    'iii'),
  (10, 8,    'jjj')

在这种情况下,我们需要使用以下查询:

DECLARE @Id int = 1 -- your UnitId
;WITH cte AS 
 (
  SELECT a.Id, a.parentId, a.name
  FROM customer a
  WHERE parentid = @Id
  UNION ALL
  SELECT a.Id, a.parentid, a.Name
  FROM customer a JOIN cte c ON a.parentId = c.id
   and c.id != @Id

  )
  SELECT parentId, Id, name
  FROM cte
go