У меня есть таблица, которая определяет иерархию:
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, оно должно проходить по иерархии до тех пор, пока не будет найдено ненулевое значение для этого поля.Короче говоря, он должен функционировать как функция объединения, за исключением иерархии строк вместо набора столбцов.
Пример:
Где [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
Пока что у меня естьthis:
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, если это поможет.Я еще не исследовал этот маршрут.