2009-11-23 6 views
1

내 날짜는 트리 구조로 구성됩니다.동일한 테이블의 중첩 된 조인 (트리 구조)

다음이 적용됩니다 (오라클 SQL 구문) :

select name, id <<<TODO LOGIC>> where id = 1 

내가

| name | id | 
| a  | 1 | 
| a.1 | 2 | 
| a.2 | 3 | 
| a.2.1 | 4 | 
| a.2.2 | 5 | 
을 얻을 것입니다 : 내가 쿼리 수 있도록, id로 전체 트리를 돌려 싶습니다
CREATE TABLE TREE 
(
    NAME VARCHAR2(20), 
    ID NUMBER(10, 0), 
    PARENT NUMBER(10, 0) 
) 
; 

INSERT INTO "TREE" (NAME, ID) VALUES ('a', '1'); 
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.1', '2', '1'); 
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2', '3', '1'); 
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2.1', '4', '3'); 
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2.2', '5', '3'); 
INSERT INTO "TREE" (NAME, ID) VALUES ('b', '6'); 

하위 트리에 대해

을 얻을 수 있습니다.

select name, id <<<TODO LOGIC>> where id = 3 

내가

| name | id | 
| a.2 | 3 | 
| a.2.1 | 4 | 
| a.2.2 | 5 | 

로 평면 항목 B에 대한, 그것은

select name, id <<<TODO LOGIC>> where id = 6 

내가 얻을 것이다 얻을 것이다 얻을 것

| name | id | 
| b  | 6 | 

그것은 밖으로 쿼리를 가입 왼쪽이 일반 보인다 이 목적을 달성하지 못하거나 뭔가를 놓치고 있습니까?

다음 쿼리는 전체 구조를 반환하지만 으로 필터링을 시작하면 문이 실패합니다.

select t1.id t1Id, t2.id t2Id, t1.name t1Name, t2.name t2Name from tree t1 left outer join tree t2 on t1.id = t2.parent 

답변

2

Oracle에서 start with - connect by 구문을 사용할 수 있습니다. 내가 실수하지 않는다면, 이것처럼 간다.

select * from Tree t 
start with t.ID = 1 connect by prior t.ID = t.Parent 

그러나 나는 즉시 그것을 점검 할 오라클이 없다. 어쩌면 그것의 prior t.Parent = t.ID. 주의해서 사용하는 것이 때때로 느릴 수 있음을 유의하십시오.

노드 사이의 모든 간접 관계 (a-a.1뿐만 아니라 a-a.2.1 등등)를 저장하기위한 테이블을 생성 할 수도 있습니다. PL/SQL 재귀 저장 프로 시저를 사용하여 채울 수 있습니다. 두 가지 방법 :

  1. 간단한 방법은 간접 테이블의 전체 리필을 수행하는 절차를 만드는 것입니다. 보고서를 실행하기 전에 보고서를 호출 할 수 있습니다.

  2. 인스턴트 효과가 필요한 경우 트리의 한 레코드에 대한 간접 관계를 업데이트하도록 리필 절차를 작성해야합니다.그런 다음 직접 삽입 및 트리에 대한 업데이트를 금지하고 InsertTree/UpdateTree와 같은 저장된 PL/SQL 프로 시저를 통해 이동하게합니다.이 프로 시저는 간접적 인 관계로 테이블을 업데이트하는 프로 시저를 호출합니다.

+0

고맙습니다, SELECT ID, 이름, 부모 FROM tree id =로 시작 하시겠습니까? 먼저 CONNECT BY id = parent; 사실 해결책입니다. 그레이트 :) –

+0

당신을 진심으로 환영합니다. 계획된 데이터 볼륨에서 쿼리 속도를 테스트하십시오. 말했듯이 (특히 테이블을 더 조인하거나 추가 조건을 추가하는 경우) 때때로 속도가 느려질 수 있습니다. –

0

이에 대한 union을 사용할 수 있습니다, 당신은 가능한 한 쿼리에서 선택 할 수 있도록 나무의 깊이를 제한 할 필요가있다.

SELECT id, name 
FROM TREE as node 
WHERE 
    node.id = :id 
UNION 
SELECT child1.id, child1.name 
FROM TREE as node 
    inner join TREE as child1 on node.id = child1.parent 
WHERE 
    node.id = :id 
UNION 
SELECT child2.id, child2.name 
FROM TREE as node 
    inner join TREE as child1 on node.id = child1.parent 
    inner join TREE as child2 on child1.id = child2.parent 
WHERE 
    node.id = :id 

여기에서 문제는 SQL이 재귀에서 매우 나쁘다는 것입니다 (관계형 구조가 실제로는 큰 반면).

완전히 동적으로 만들려면 트리의 각 수준에 대해 쿼리를 사용하거나 사용할 수있는 것이 있으면 데이터베이스 엔진 전용 SQL 확장을 사용하십시오.

3

트리 구조가있는 경우 계층 적 쿼리가 필요할 수 있습니다. 여기에 있습니다 :

select t.* 
    from tree t 
connect by prior t.id = t.parent 
    start with t.id = :id 
    order siblings by t.id 

자세한 내용은 Hierarchical Queries을 참조하십시오.