我有一个定义层次结构的表:
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 字段为空,则它应该向上遍历层次结构,直到遇到该字段的非空值。简而言之,它应该像 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 聚合函数。我还没有探索过那条路线。