2009-08-03 10 views
2

テーブル内のツリーを表しています。特定の要素のルートノード(TOP ID)を取得する必要があります。ルートノードは常にParentIDnullです。例えば、テーブルは次のように見える場合:SQL Server 2005で再帰のヘルプが必要

ID ParentID 
1 null 
2 null 
3 null 
4 2 
5 1 
6 2 
7 6 
8 4 
9 8 
10 6 

ときID=10TOP ID = 2ID=9の場合、TOP ID = 3。等々。 IDが与えられたときにTOP IDを返すSQLサーバー関数を書くことは可能ですか?

答えて

1

SQL 2003より前のSQL(つまりSQL Server 2000)の再帰は多少醜いです。ツリー内の各レベルについて、元のテーブルに別の結合ステートメントを書き戻す必要があります。階層のレベル数が固定されていれば、このようなことを書くことができます。

create table #Hell (
parent int, 
id int, 
name varchar(30) 
) 

insert into #Hell values (NULL, 1, 'The Boss') 
insert into #Hell values (1, 2, 'The Boss'' PA') 
insert into #Hell values (1, 3, 'Production Director') 
insert into #Hell values (3, 4, 'Jim''l Fixit') 


select * from #Hell H1 
inner join #Hell H2 
ON H1.id=H2.parent 
inner join #Hell H3 
ON H2.id=H3.parent 
WHERE H3.Id=4 --Find the boss for Jim 

drop table #Hell 

幸いにもSQL Server 2005では、再帰的な操作が非常に簡単に書き込むことができますと共通テーブル式を持っています。参照参照http://www.4guysfromrolla.com/webtech/071906-1.shtml

また、データベース内のツリーを表すさまざまな方法にも注意する必要があります。このプレゼンテーションからSQLのツリー上のスライドを見てくださいhttp://www.slideshare.net/billkarwin/sql-antipatterns-strike-back

+1

"with"演算子は実際には "共通テーブル式"(CTE)と呼ばれ、SQL Server固有の拡張ではありませんが、SQL:2003標準の一部です。 –

+0

私はそれがMicrosoftのことだと思って何らかの理由で感謝しますが、PostgresはWITH RECURSIVEを使ってCTEをサポートしています。 – pjp

2

MSDNには、再帰クエリを書き込むためにCommon Table Expressionsを使用するための非常に良い例があります。 SQL Server 2005の前にこれを行うことは、後部で大きな苦痛でした(今のところ、古いServer 2000アプリケーションでのその正確な問題に対処する)。

0

MSDN brough up this articleこれは、このサイトで許可されている形式で取得する可能性が高いと考えられます。

3

sprocに与えられた任意のID - (@ID)に対して親(親ID = null)を見つけるsprocの再帰的な例です。あなたはこれを探していますか?

WITH recurseUp (ID, ParentID) 
    AS 
    (
     SELECT ID, ParentID 
     FROM myTable 
     WHERE ID = @ID 
     UNION ALL 
     SELECT b.ID, b.ParentID 
     FROM recurseUp a JOIN myTable b 
     ON (a.ParentID = b.ID) 
    ) 
SELECT ID FROM recurseUP WHERE ParentID is null 
+0

この例はうまくいきますが、このすべてをViewまたはSQL関数に入れる方法は不可能でしょうか? – Vytas

0

ことは可能だが、私が知っている唯一の方法は、CURSORと再帰ストアドプロシージャを使用することです。これは、パフォーマンスの観点から(通常)行うことは、本当に悪い方法です。可能であれば、あなたが移動しながらコードを介して更新し続ける追加ルート親ノードを持つコストを考慮する必要があります。

+0

CTEはサーバー2005以降のプロセスを非常に簡単にします。それは実際にP.I.T.A. for the Sever 2000 – TheTXI

0
WITH q AS 
     (
     SELECT id, parentID 
     FROM mytable 
     WHERE id = 10 
     UNION ALL 
     SELECT mytable.id, mytable.parentid 
     FROM q 
     JOIN mytable 
     ON  mytable.parentId = q.id 
     ) 
SELECT * 
FROM q 
WHERE parentID IS NULL 
関連する問題