Итак, у меня есть древовидная структура, реализованная в виде вложенного набора. У меня также есть элемент управления TreeView, который отображает указанную древовидную структуру.Получение всех детей первого уровня из «открытых» элементов в модели вложенных множеств
Первоначально все элементы «закрыты», что означает, что я вижу только предметы первого уровня. Теперь пользователь может открывать/закрывать элементы по своему желанию, и я отслеживаю открытые элементы. Все открытые элементы вставляются в TreeView.
я получить их, используя эту инструкцию:
select opened.tt_id, tree_test.*
from tree_test as opened
join tree_test on tree_test.tt_nsleft between opened.tt_nsleft + 1 and opened.tt_nsright
and not exists (select * from tree_test t1 where t1.tt_nsleft between opened.tt_nsleft + 1 and opened.tt_nsright and tree_test.tt_nsleft between t1.tt_nsleft + 1 and t1.tt_nsright - 1)
where opened.tt_id in (1, 3, 8)
order by tt_nsleft
Пользователь может drilll вниз по желанию открытия 3-го или 4-го уровня элементов. И здесь я столкнулся с проблемой: если у пользователя есть некоторые элементы уровня 3-го, 4-го и т. Д., И теперь он закрывает своего родителя 1-го уровня, вышеупомянутый запрос все равно вернет все эти подпункты.
Каков наилучший способ «подтвердить» открытые элементы, чтобы остались только те, которые являются прямыми детьми на самом деле видимых элементов?
У меня есть решение, которое я думаю, что это довольно расточителен и он просто проверяет открытые элементы против результирующего набора:
select opened.tt_id, tree_test.*
from tree_test as opened
join tree_test on tree_test.tt_nsleft between opened.tt_nsleft + 1 and opened.tt_nsright
and not exists (select * from tree_test t1 where t1.tt_nsleft between opened.tt_nsleft + 1 and opened.tt_nsright and tree_test.tt_nsleft between t1.tt_nsleft + 1 and t1.tt_nsright - 1)
where opened.tt_id in (1, 3, 8)
and opened.tt_id in (
select tree_test.tt_id
from tree_test as opened
join tree_test on tree_test.tt_nsleft between opened.tt_nsleft + case when opened.tt_nsleft = 1 then 0 else 1 end and opened.tt_nsright
and not exists (select * from tree_test t1 where t1.tt_nsleft between opened.tt_nsleft + 1 and opened.tt_nsright and tree_test.tt_nsleft between t1.tt_nsleft + 1 and t1.tt_nsright - 1)
where opened.tt_id in (1, 3, 8)
)
order by tt_nsleft
Это работает, потому что результирующий набор содержит только первый уровень детей всех запрошенных пунктов , Если элемент не находится в результирующем наборе, он должен произойти из уровня ниже. Это, конечно, означает двойную работу для сервера, так как на самом деле нужно собрать данные дважды, чтобы иметь возможность отфильтровывать недопустимые открытые элементы.
Альтернативным решением будет поиск родительского элемента открытого объекта и проверка его против списка открытых элементов (+ null для элемента верхнего уровня). Однако запрос для этого не кажется намного легче.
Есть ли третий вариант, который я здесь отсутствует?