web-dev-qa-db-ja.com

クエリで再帰を使用して、親のすべての子を取得し、次にその子を取得する方法

私はこのような構造を持っています:

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

この構造には、メインユニット、サブユニット、サブユニットの3つのレベルがあります。

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レベルがありますが、正しい結果を得るにはどうすればよいですか?

17
user1893999
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 のデモ

36

親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
2
user2231692