2009-03-18 9 views
9

나는 최근에 Nested Set Model에서 쓰레기를 사용 해왔다. 나는 모든 유용한 조작과 뷰를위한 쿼리 디자인을 즐겼다. 내가 붙어있는 한 가지 방법은 바로 밑의 자식을 선택하는 것입니다 (그리고 자식들, 더 이상의 자손은 아닙니다!).노드의 하위 항목을 쿼리하는 간단한 방법이 있습니까?

솔직히 말해서 나는 방법을 알고 있지만 관리하기 어려운 양의 SQL이 관련되어 있습니다. 좀 더 간단한 해결책이 있다고 확신합니다.

답변

9

게시 한 기사를 읽었습니까? 나는 테이블에서 "PARENT_ID"를 포함 - 그것은 내가 (이 부정 행위) 할 것은 내가 인접리스트와 중첩 된 세트를 결합, 제목 그러나

SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth 
FROM nested_category AS node, 
    nested_category AS parent, 
    nested_category AS sub_parent, 
    (
     SELECT node.name, (COUNT(parent.name) - 1) AS depth 
     FROM nested_category AS node, 
     nested_category AS parent 
     WHERE node.lft BETWEEN parent.lft AND parent.rgt 
     AND node.name = 'PORTABLE ELECTRONICS' 
     GROUP BY node.name 
     ORDER BY node.lft 
    )AS sub_tree 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
    AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt 
    AND sub_parent.name = sub_tree.name 
GROUP BY node.name 
HAVING depth <= 1 
ORDER BY node.lft; 

"노드의 즉시 부하 직원 찾기"아래의 , 그래서 나는 노드의 자식들에게 쉽게 물어볼 수있다.

+0

를 "... 내가 ... 인접리스트와 중첩 된 세트를 결합"하! 그게 내가하고있는 일이야. 나는 adj. 조 Celko에 의해 쿼리를 기반으로 목록보기. 그것은 엄청난 양의 코드처럼 보입니다. 심지어 링크 된 기사의 솔루션은 ... 장황하다. – Metaphile

+0

내 말은, 노드의 자손을 _all_을 선택하는 것과 비교하면 다음과 같습니다. SELECT * 노드에서 where nodes.leftBound BETWEEN parentLeftBound AND parentRightBound; – Metaphile

+0

음, "child_view"는 매우 간단합니다. SELECT * FROM nodes parent_id = 123456 : D –

7

하위 쿼리 또는 상위 열 중복이 없으면 쉽게 수행 할 수 있습니다! 예를 들어, 주어진 부모의 왼쪽과 오른쪽은 이미 알려져 있습니다

입니다
SELECT child.id 
FROM nodes AS child 
LEFT JOIN nodes AS ancestor ON 
    ancestor.left BETWEEN @parentleft+1 AND @parentright-1 AND 
    child.left BETWEEN ancestor.left+1 AND ancestor.right-1 
WHERE 
    child.left BETWEEN @parentleft+1 AND @parentright-1 AND 
    ancestor.id IS NULL 

, "문제의 노드의 모든 후손으로부터는 자신과 노드 사이에 조상과 사람을 선택".

+0

성능면에서 어느 대답이 더 좋은지 궁금합니다. 그러나 두 솔루션 모두 작동합니다. 이것은 좀 더 조밀 해 보입니다. – andreas

+0

매우 큰 나무의 경우 데이터베이스에서 중첩 루프를 수행해야하기 때문에 MySQL에서 성능이 떨어지고 SQL 서버에서 성능이 떨어지는 것을 발견했습니다. 우리는 코드를 변경하여 모든 자손을 검색 한 다음 응용 프로그램 코드에서 자손으로 정리합니다. – user393274

+0

@andreas 이것은 받아 들인 대답과 매우 흡사합니다. 차이점은 자식을 세고 자식이 1 인 자식으로 필터링하는 대신 조상이 NULL인지 확인하여 필터링합니다. 즉, 정렬 작업이 적고 카운트 단계). 속도는 빨라야하지만 테스트하지는 않았습니다. – Ariel

5

는이 하나 더

사용자 "bobince는"거의 있었다 작다. 내가 알아 낸 것이고, MySQL보다 약간의 MySQL 경험이 있기 때문에 나에게 효과가있다. 그러나, 나는 왜 bobince의 대답이 사람들을 놀라게 할지를 알 수 있습니다. 그의 질문은 불완전하다. 먼저 mysql 변수에 parent_left와 parent_right를 선택해야합니다.

아래의 두 쿼리는 테이블이 오른쪽 열에는 rgt라는 및 기본 키가 id라는 것을, 당신의 왼쪽 열이 lft라는, tree라는 가정합니다. 필요에 맞게이 값을 변경하십시오. 또한 첫 번째 select 문을 검사하십시오. 노드 5의 바로 후손을 찾고있는 것을 볼 수 있습니다. 원하는 노드의 자식을 찾기 위해 숫자 5를 변경하십시오.

저는 개인적으로 이것은 지금까지 제시된 것보다 더 매끄럽고 섹시하며 효율적인 쿼리라고 생각합니다.

SELECT `lft`, `rgt` INTO @parent_left, @parent_right FROM efm_files WHERE `id` = 5; 
SELECT `child`.`id` 
FROM `tree` AS `child` 
LEFT JOIN `tree` AS `ancestor` ON 
    `ancestor`.`lft` BETWEEN @parent_left+1 AND @parent_right-1 AND 
    `child`.`lft` BETWEEN `ancestor`.`lft`+1 AND `ancestor`.`rgt`-1 
WHERE 
    `child`.`lft` BETWEEN @parent_left+1 AND @parent_right-1 AND 
    `ancestor`.`id` IS NULL 
+0

'efm_files '이란 무엇입니까? – Madbreaks

+0

efm_files는 mysql 데이터베이스에있는 테이블의 이름입니다. 데이터베이스의 고유 한 테이블 이름으로 바꾸십시오. – mrbinky3000

0

저는 necro 게시물을 쓰는 것을 알고 있습니다. 하지만 제 의견은 여기에 있습니다.

중첩 된 집합에 "깊이"열을 포함하지 않는 이유는 무엇입니까? 깊이 열은 항목의 "수준"을 나타냅니다. 그래서

는, 너무,

select c.*
from tree as p
join tree as c on (c.left > p.left and c.right < p.right and c.depth = p.dept + 1) where p.id = @parentID

+0

엄격하게 말해서 더 이상 중첩 된 집합이 아니기 때문에 계층 적 모델의 조합입니다. 그리고 종종 문제를 해결하기 위해 모델을 변경하는 것은 선택 사항이 아닙니다. – Madbreaks

0

내가 깊이 열이 가고 싶어 할, 항목의 즉각적인 차일을 선택합니다. 하지만 Wikipedia link가 선택한 답변과 함께 답변의 좋은 최소화 버전이 발견

SELECT Child.Node, Child.LEFT, Child.RIGHT 
FROM Tree AS Child, Tree AS Parent 
WHERE 
     Child.Depth = Parent.Depth + 1 
     AND Child.LEFT > Parent.LEFT 
     AND Child.RIGHT < Parent.RIGHT 
     AND Parent.LEFT = 1 -- Given Parent Node Left Index 

Wikipedia

+0

왼쪽 및 오른쪽 ID와 함께 * 추가 ​​* 깊이 열이 필요합니다. – Youngjae

0

사용합니다.

SELECT DISTINCT Child.Name 
FROM ModelTable AS Child, ModelTable AS Parent 
WHERE Parent.Lft < Child.Lft AND Parent.Rgt > Child.Rgt -- associate Child Nodes with ancestors 
GROUP BY Child.Name 
HAVING MAX(Parent.Lft) = @parentId -- Subset for those with the given Parent Node as the nearest ancestor 

, 당신의 LINQ에 그것을 표현하려고하면 링크를 클릭하십시오 : https://stackoverflow.com/a/25594386/361100

관련 문제