Итак, если я правильно понял, у вас есть известный родительский компонент, и известный код актива. Используя их, вы хотите построить дерево, охватывающее пути (из-за отсутствия лучшего слова) от родительского компонента к рассматриваемому активу?
Вот попытка сделать это. Мы начнем с создания фиктивных данных, которые будут использоваться для тестирования:
declare @component table (
id int primary key,
code nvarchar(50) not null,
parent_id int null,
asset_id int null
)
declare @asset table (
id int primary key,
code nvarchar(50)
)
insert into @asset values (1, '2018100000')
insert into @asset values (2, '2019100000')
insert into @component values(1, 'root', null, null)
insert into @component values(2, 'c1', 1, null)
insert into @component values(3, 'c2', 1, null)
insert into @component values(4, 'c3', 1, null)
insert into @component values(5, 'c2_c1', 3, null)
insert into @component values(6, 'c2_c2', 3, 1)
insert into @component values(7, 'c2_c1_c1', 5, 2)
insert into @component values(8, 'c2_c1_c2', 5, 1)
insert into @component values(9, 'c2_c1_c2_c1', 8, 2)
insert into @component values(9, 'c2_c1_c1_c1', 7, 1)
Затем мы объявляем пару рекурсивных CTE
: s и используем их для получения вывода:
declare @specParentId int
declare @assetCode nvarchar(50)
set @specParentId = 3
set @assetCode = '2018100000'
;with compRecurseDown as (
select c.id, c.code, parent_id, 0 as level, c.asset_id
from @component c
where c.id = @specParentId
union all
select c.id, c.code, c.parent_id, p.level + 1, c.asset_id
from @component c
join compRecurseDown p on c.parent_id = p.id
), assetRecurseUp as (
select c.*
from @asset a
join @component c on a.id = c.asset_id
where a.code = @assetCode
union all
select c.*
from @component c
join assetRecurseUp p on p.parent_id = c.id
)
select crd.*, a.code as asset_code
from compRecurseDown crd
left outer join @asset a on crd.asset_id = a.id
where crd.id in (
select id from assetRecurseUp
)
order by level
В этом случае мы ищем актив 2018100000
под компонентом с идентификатором 3
. Результат:
| id | code | parent_id | level | asset_id | asset_code |
|----|----------|-----------|-------|----------|------------|
| 3 | c2 | 1 | 0 | NULL | NULL |
| 5 | c2_c1 | 3 | 1 | NULL | NULL |
| 6 | c2_c2 | 3 | 1 | 1 | 2018100000 |
| 8 | c2_c1_c2 | 5 | 2 | 1 | 2018100000 |
Так как это работает? Сначала мы объявляем compRecurseDown
CTE. Он использует известный родительский компонент в качестве anchor
, а затем рекурсивно находит все дочерние заметки в этом узле.
assetRecurseUp
CTE начинается с поиска всех компонентов, связанных с известным активом. Затем он рекурсивно добавляет все родительские узлы на основе этого.
Наконец, мы запрашиваем комбинацию этих двух, чтобы получить окончательный набор результатов.