3

私のテーブルでは、各レコードには直接の親へのポインターがあり、特定のレコードのすべての子孫 (直接的かどうか (息子の息子)) を照会する方法を知る必要があります。

事実:

  • 木の深さが分からないので、すべての葉が必要です
  • 一部のレコードには子レコードがない可能性があります
  • 私はSqlServer 2012で実行しています

そのようなクエリの書き方を誰か教えてもらえますか?

4

2 に答える 2

4

Josh Wallace からのクエリに基づいて構築し、子孫を取得します。

declare @people table
(
    Id int,
    Name nvarchar(50),
    ParentId int
)

insert into @people values (1, 'Frank', null)
insert into @people values (2, 'Shane', null)
insert into @people values (3, 'George', 1)
insert into @people values (5, 'Hank', 1)
insert into @people values (7, 'Abigail', 3)
insert into @people values (8, 'Ben', 3)
insert into @people values (9, 'Charlie', 5)
insert into @people values (10, 'Dave', 5)
insert into @people values (11, 'Homer', 5)
insert into @people values (12, 'Junebug', 7)
insert into @people values (13, 'Bart', 11)
insert into @people values (14, 'Lisa', 11)


;with descendents AS (
    -- Anchor member definition
    select p.Id, p.Name, p.ParentId, Level = 0 
    from @people p 
    where p.Id = 1 -- person to search for descendents 

    union all

    -- Recursive member definition
    select p.Id, p.Name, p.ParentId, Level + 1
    from @people p 
    inner join descendents a on p.ParentId = a.Id
)


select 
    a.Level, ParentID = p.Id, Parent = p.Name, a.Id, Child = a.Name
from descendents a 
    left join @people p on p.Id = a.ParentId
order by a.Level 
于 2013-01-16T16:14:57.367 に答える
1

再帰に CTE を使用することは、私にとって最も簡単な方法のように思えます。ここに例を示します...

DECLARE @people TABLE
(
    Id INT,
    Name NVARCHAR(50),
    ParentId INT
)

INSERT INTO @people (Id, Name, ParentId) VALUES (1, 'Abigail', null)
INSERT INTO @people (Id, Name, ParentId) VALUES (2, 'Ben', 5)
INSERT INTO @people (Id, Name, ParentId) VALUES (3, 'Charlie', 2)
INSERT INTO @people (Id, Name, ParentId) VALUES (4, 'Dave', 1)
INSERT INTO @people (Id, Name, ParentId) VALUES (5, 'Ed', 6)
INSERT INTO @people (Id, Name, ParentId) VALUES (6, 'Frank', null)

;WITH ancestors AS (
 SELECT Id, Name, ParentId FROM @people WHERE Id = 3 
 UNION ALL
 SELECT p.Id, p.Name, p.parentId FROM @people p
 INNER JOIN ancestors a ON a.parentId = p.Id --This inner join causes the recurrsion
)
SELECT Id, Name, ParentId FROM ancestors

子から祖先に移動するには、ON ステートメントを逆に切り替えます。

DECLARE @people TABLE
(
    Id INT,
    Name NVARCHAR(50),
    ParentId INT
)

INSERT INTO @people (Id, Name, ParentId) VALUES (1, 'Abigail', null)
INSERT INTO @people (Id, Name, ParentId) VALUES (2, 'Ben', 5)
INSERT INTO @people (Id, Name, ParentId) VALUES (3, 'Charlie', 2)
INSERT INTO @people (Id, Name, ParentId) VALUES (4, 'Dave', 1)
INSERT INTO @people (Id, Name, ParentId) VALUES (5, 'Ed', 6)
INSERT INTO @people (Id, Name, ParentId) VALUES (6, 'Frank', null)

;WITH ancestors AS (
 SELECT Id, Name, ParentId FROM @people WHERE Id = 6
 UNION ALL
 SELECT p.Id, p.Name, p.parentId FROM @people p
 --INNER JOIN ancestors a ON a.parentId = p.Id --It was this to go down...
   INNER JOIN ancestors a ON a.Id = p.parentId --Now use this to go up the tree
)
SELECT Id, Name, ParentId FROM ancestors
于 2013-01-16T09:30:59.113 に答える