1

最初または中間または最後にIDを指定すると、それらの間にリンクされているすべての行を検索したい。これにより再帰でセグメントを与えられた親と子を取得するSQL

は、私は2と3を取得します、@Idが2に等しい場合、再帰的に

declare @T table(
    Id int primary key, 
    Name nvarchar(255) not null, 
    ParentId int) 

insert into @T values 
(1, 'A', NULL), 
(2, 'B', 1), 
(3, 'C', 2), 
(4, 'D', NULL), 
(5, 'E', 1) 

declare @Id int = 2 

;with cte as 
( 
    select T.* 
    from @T as T 
    where T.Id = @Id 
    union all 
    select T.* 
    from @T as T 
    inner join cte as C 
     on T.ParentId = C.Id 
) 
select * 
from cte 

子要素を発見した。しかし、私はこのケースでは、あまりにも親を取得したい1.

私はこれを取得したい:

場合は、id = 1

1 A NULL 
2 B 1 
3 C 2 
5 E 1 

ID = 2の場合

1 A NULL 
2 B 1 
3 C 2 
5 E 1 

ID = 3

1 A NULL 
2 B 1 
3 C 2 
5 E 1 

場合は、id = 5

1 A NULL 
2 B 1 
3 C 2 
5 E 1 

私はこれをどのように修正することができます場合は、id = 4

4 D NULL 

場合は?

+0

あなたの質問を編集して、所望の出力を追加することができますか? – GuidoG

+0

なぜid = 1の場合、 '5 E 1'レコードを取得すべきではありませんか? –

+0

申し訳ありませんが悪いです。修正されました。 –

答えて

0

私はあなたを持っています:

私はテストのための別の家族を作成しました。

あなたがする必要がある最初の事はあなたの選択したIDの最古の祖先を見つけるために、クエリを作成することです。それが以下の最初のCTEです。あなたはそれを指定して、私はそれを@Eveと呼んで、イブのすべての子供たちを見つけます。

Here is the exampleあなたは非常に有用だった

create table UserType (
    Id int, 
    name nvarchar(255), 
    parentid int) 

insert into UserType values 
(1, 'A', NULL), 
(2, 'B', 1), 
(3, 'C', 2), 
(4, 'D', NULL), 
(5, 'E', 1), 
(6, 'F', NULL), 
(7, 'G',  6), 
(8, 'H',  7); 

DECLARE @eve BIGINT; --ancestor 
DECLARE @id BIGINT; 
SET @id = 8; --This is where you choose 

WITH tblParent AS --CTE for oldest ancestor 
(
    SELECT * 
     FROM UserType WHERE Id = @id 
    UNION ALL 
    SELECT UserType.* 
     FROM UserType JOIN tblParent ON UserType.Id = tblParent.ParentId 
) 
select 
@eve = (select top 1 id from tblParent order by id); 

WITH tblChild AS --CTE for all @eve and all children 
(
    SELECT * 
     FROM UserType WHERE id = @eve 
    UNION ALL 
    SELECT UserType.* FROM UserType JOIN tblChild ON UserType.ParentId = tblChild.Id 
) 
SELECT * FROM tblChild 
order by id 


OPTION(MAXRECURSION 32767) 

Props to CodeProjectで遊ぶことができます。

+0

あなたの答えをありがとう。私は私の希望の出力を表示するために私の質問を更新しました。クエリは、それらの間のすべてのリンクを見つける必要があります。 ID = 3または5を変更した場合、コードは機能しません –

+0

@MaximusDecimusはコメントしてくれてありがとうございます。あなたは、親と親のすべての子孫があなたの宣言されたIDを求めますか?例えば、5の子はnull、5のParentは1です。しかし、すべてのChildren(2)とGrandChildren(3)を1にしますか? – EoinS

+0

リンクされているすべての行をparentidで示します。祖父母、両親、子供たちなど。関連するすべての行私は最大4レベルを持っていますが、私が孫を見つけた場合、私はすべての子供、両親、祖父母、そしてこれらすべての祖父母に関連するすべてを見つけることができます。 –

0

このようなものを試してください。

declare @tbl table(--test table var 
Id int, 
name nvarchar(255), 
parentid int) 

insert into @tbl values -- test data 
(1, 'A', NULL), 
(2, 'B', 1), 
(3, 'C', 2), 
(4, 'D', NULL), 
(5, 'E', 1), 
(6, 'F', NULL), 
(7, 'G',  6), 
(8, 'H',  7); 

declare @id int = 7 

;with parents as (
select id,name,parentid, 0 lvl 
from @tbl 
where [email protected] 
union all 
select t.id,t.name,t.parentid, lvl-1 
from @tbl t 
inner join parents p on t.Id=p.parentid --up the tree 
) 
,children as (
select id,name,parentid, 0 lvl 
from @tbl 
where [email protected] --select single record 
union all 
select t.id,t.name,t.parentid, lvl+1 
from @tbl t 
inner join children c on c.Id=t.parentid -- down the tree 
) 
select * from parents 
union --combine results 
select * from children 
order by lvl 
+0

はあなたの貴重な答えをどうもありがとうございます、私は数5を取得できませんでした。私が2または3を検索したときには、1または5を直接検索しますが、ブランチのすべての行を取得したい場合は、別のシナリオのモデルとしてコードを使用しました。 –

関連する問題