階層を定義するテーブルがあります。
Create Table [example] (
id Integer Not Null Primary Key,
parentID Integer Null,
largeData1 nVarChar(max) Null,
largeData2 nVarChar(max) Null);
-- largeData3...n also exist
Insert Into [example] (id, parentID, largeData1, largeData2)
Select 1, null, 'blah blah blah', null Union
Select 2, 1, null, null Union
Select 3, 1, 'foo bar foobar', null Union
Select 4, 3, null, 'lorem ipsum' Union
Select 5, 4, null, null;
このデータの階層図:
特定の [id] 値に対して単一の行を返すクエリを作成したいと考えています。行には、その行の [id] および [parentID] 情報が含まれている必要があります。[largeData1...n] フィールドも含まれている必要があります。ただし、largeData フィールドが null の場合は、そのフィールドの null 以外の値が検出されるまで、階層を上に移動する必要があります。つまり、一連の列ではなく行の階層を横断することを除いて、coalesce 関数のように機能する必要があります。
例:
[id] = 1 の場合:
id: 1
parentID: null
largeData1: blah blah blah
largeData2: null
[ID] = 2
id: 1
parentID: 1
largeData1: blah blah blah
largeData2: null
[ID] = 3
id: 3
parentID: 1
largeData1: foo bar foobar
largeData2: null
[ID] = 4
id: 4
parentID: 3
largeData1: foo bar foobar
largeData2: lorem ipsum
[ID] = 5
id: 5
parentID: 4
largeData1: foo bar foobar
largeData2: lorem ipsum
これまでのところ、私はこれを持っています:
Declare @id Integer; Set @id = 5;
With heirarchy
(id, parentID, largeData1, largeData2, [level])
As (
Select id, parentID, largeData1,
largeData2, 1 As [level]
From example
Where id = @id
Union All
Select parent.id, parent.parentID,
parent.largeData1,
parent.largeData2,
child.[level] + 1 As [level]
From example As parent
Inner Join heirarchy As child
On parent.id = child.parentID)
Select id, parentID,
(Select top 1 largeData1
From heirarchy
Where largeData1 Is Not Null
Order By [level] Asc) As largeData1,
(Select top 1 largeData2
From heirarchy
Where largeData2 Is Not Null
Order By [level] Asc) As largeData2
From example
Where [id] = @id;
これにより、探している結果が返されます。ただし、クエリ プランによると、プルバックする largeData フィールドごとに階層を個別に通過させています。
これをより効率的にするにはどうすればよいですか?
これは明らかに、より複雑な問題の単純化されたバージョンです。最後のクエリはデータを XML 形式で返すため、FOR XML 句を含むソリューションは問題ありません。
これが役立つ場合は、CLR 集計関数を作成できます。私はまだそのルートを探索していません。