私は隣接リストによって記述された階層を持っています。必ずしも単一のルート要素である必要はありませんが、私は、ヒラリー内のリーフ(終端)項目を識別するデータを持っています。だからこのように見える階段...SQL階層 - 与えられたノードのすべての祖先の完全なパスを解決します。
1
- 2
- - 4
- - - 7
- 3
- - 5
- - 6
8
- 9
...このような表で説明されます。 注::私はこのフォーマットを変更する能力がありません。ここ
id parentid isleaf
--- -------- ------
1 null 0
2 1 0
3 1 0
4 2 0
5 3 1
6 3 1
7 4 1
8 null 0
9 8 1
は、サンプルテーブル定義とデータである。このことから
CREATE TABLE [dbo].[HiearchyTest](
[id] [int] NOT NULL,
[parentid] [int] NULL,
[isleaf] [bit] NOT NULL
)
GO
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (1, NULL, 0)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (2, 1, 0)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (3, 1, 0)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (4, 2, 0)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (5, 3, 1)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (6, 3, 1)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (7, 4, 1)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (8, NULL, 0)
INSERT [dbo].[HiearchyTest] ([id], [parentid], [isleaf]) VALUES (9, 8, 1)
GO
、私は、任意のIDを提供し、それぞれのすべての子孫を含むすべての祖先のリストを取得する必要があります。
id descendentid
-- ------------
1 1
1 3
1 6
3 3
3 6
6 6
- ID 6ちょうどその親、ID 3は3と6 のdecendentsを持つことになり、それ自体
- あります。私はID = 6の入力を提供するのであれば、私は次のように期待します
- 親、ID 1は、私は、階層内の各レベルでロールアップ計算を提供するためにこのデータを使用する1のdecendents、3、6
を有するであろう。上記のデータセットを取得できるとすれば、これはうまくいきます。
私はこれを、2つの反発的な頭字語を使用して達成しました.1つは、検索で各ノードの「終端」項目を取得することです。次に、私が選択したノードの完全な祖先を取得する2番目のノード(つまり、6は6,3,1に解決されます)が立ち上がり、フルセットを取得します。私は何かが欠けていることを望んでおり、これは1ラウンドで達成することができます。ここでは、二重再帰コード例です。
declare @test int = 6;
with cte as (
-- leaf nodes
select id, parentid, id as terminalid
from HiearchyTest
where isleaf = 1
union all
-- walk up - preserve "terminal" item for all levels
select h.id, h.parentid, c.terminalid
from HiearchyTest as h
inner join
cte as c on h.id = c.parentid
)
, cte2 as (
-- get all ancestors of our test value
select id, parentid, id as descendentid
from cte
where terminalid = @test
union all
-- and walkup from each to complete the set
select h.id, h.parentid, c.descendentid
from HiearchyTest h
inner join cte2 as c on h.id = c.parentid
)
-- final selection - order by is just for readability of this example
select id, descendentid
from cte2
order by id, descendentid
追加詳細:「本当の」階層は例よりもはるかに大きくなります。それは技術的に無限の深さを持つことができますが、現実的には10レベルを超えることはほとんどありません。
要約すると、階層的に2回繰り返すのではなく、1つの再帰的cteでこれを達成できるかどうかです。
https://msdn.microsoft.com/en-us/library/bb677173.aspxここでは、正確にこれを対象としたいくつかの新しい階層機能に関するMicrosoftの記事があります。 – Matt
@Matt - 提案をいただきありがとうございますが、上記の私の注意は、データ構造を変更する能力がないことを示しています(私のテーブルではありません)。だから、私はhierarchyid列を追加する能力がありません。さらに、階層IDに関する私の経験では、私が求めていることをする方法を見ていない。id = 6の入力に基づいて、このIDのすべての祖先の完全な子孫リストが必要であることがわかります。 –
私はすぐに読んだ:)再帰的なcteは、私が再び読んで、私が助けることができるものかどうかを確認するルートです。 – Matt