2014-09-09 2 views
0

그래서 트리 구조가 중첩 세트로 구현되었습니다. 또한 트리 구조를 표시하는 TreeView 컨트롤이 있습니다.중첩 세트 모델에서 "열린"항목의 모든 1 차 하위를 가져옴

처음에는 모든 요소가 "닫힙니다"라는 의미로, 첫 번째 수준의 항목 만 표시됩니다. 이제 사용자는 자유롭게 항목을 열거 나 닫을 수 있으며 열린 항목을 추적 할 수 있습니다. 열려있는 모든 항목이 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 

사용자는 의지 개방 3 번째 또는 4 번째 수준 항목에서 아래로 drilll 수 있습니다. 여기에 문제가 발생합니다. 사용자가 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)에 대해 확인하는 것입니다. 그러나 그 쿼리는 훨씬 가벼워 보이지 않습니다.

세 번째 옵션이 여기에 있습니까?

답변

0

많은 내가 어떤 기본적인 중첩 된 일련의 작업만큼이나 우아한 해결책 발견 실험 (그리고 실패) 후 :

select tree_test".* 
    from tree_test 
where not exists (
     select * 
      from tree_test parents 
     where tree_test.tt_nsleft between (parents.tt_nsleft + 1) and parents.tt_nsright 
     and not (parents.tt_id in (12384898975268895, 12384898975268897, 12384898975268902)) 
    ) 

효과적으로,이 쿼리는 말한다 : 더이 곳 "모든 항목을 선택을 ""에 속하지 않은 ID를 가진 부모. "열린"항목을 지정하는 조건은 사실상 유효하며 항목 ID 일 필요는 없습니다.