Вы правы, первый шаг состоит в том, чтобы идентифицировать конечные узлы через их свойство right, равное left + 1. Следующий шаг - найти все родительские узлы для этих конечных узлов: у них слева меньше, чем у листа прямо больше, чем у листа. И последний шаг - исключить всех родителей, кроме того, который имеет наибольшее левое значение (т. Е. Находится ближе всего к конечному узлу).
Пример в T-SQL, где l - это листовой узел, p1 - прямой родитель, которого мы ищем, а p2 используется для отсеивания всех непрямых родителей.
Сначала создайте тестовую таблицу с данными вашего примера:
if object_id('tempdb..#nsm') is not null
drop table #nsm;
select v.node, v.parent, v.lft, v.rgt
into #nsm
from (
values
('A' , NULL, 1, 16),
('B' , 'A' , 2, 15),
('E' , 'B' , 3, 8),
('F' , 'E' , 4, 5),
('H' , 'E' , 6, 7),
('C' , 'B' , 9, 14),
('D' , 'C' , 10, 11),
('G' , 'C' , 12, 13)
) v (node, parent, lft, rgt)
А вот запрос, который возвращает оба запрошенных узла C и E:
select p1.node, p1.parent, p1.lft, p1.rgt
from #nsm p1
where exists (
select *
from #nsm l
where l.rgt = l.lft + 1
and p1.lft < l.lft
and p1.rgt > l.rgt
and not exists (
select *
from #nsm p2
where p2.lft < l.lft
and p2.rgt > l.rgt
and p2.lft > p1.lft
)
)