Oracle 트 리 작업 (select... start with... connect by... prior)
1. 테스트 테이블 과 테스트 데이터 준비
--
create table tb_menu(
id number(10) not null, -- id
title varchar2(50), --
parent number(10) --parent id
)
--
insert into tb_menu(id, title, parent) values(1, ' 1',null);
insert into tb_menu(id, title, parent) values(2, ' 2',null);
insert into tb_menu(id, title, parent) values(3, ' 3',null);
insert into tb_menu(id, title, parent) values(4, ' 4',null);
insert into tb_menu(id, title, parent) values(5, ' 5',null);
--
insert into tb_menu(id, title, parent) values(6, ' 6',1);
insert into tb_menu(id, title, parent) values(7, ' 7',1);
insert into tb_menu(id, title, parent) values(8, ' 8',1);
insert into tb_menu(id, title, parent) values(9, ' 9',2);
insert into tb_menu(id, title, parent) values(10, ' 10',2);
insert into tb_menu(id, title, parent) values(11, ' 11',2);
insert into tb_menu(id, title, parent) values(12, ' 12',3);
insert into tb_menu(id, title, parent) values(13, ' 13',3);
insert into tb_menu(id, title, parent) values(14, ' 14',3);
insert into tb_menu(id, title, parent) values(15, ' 15',4);
insert into tb_menu(id, title, parent) values(16, ' 16',4);
insert into tb_menu(id, title, parent) values(17, ' 17',4);
insert into tb_menu(id, title, parent) values(18, ' 18',5);
insert into tb_menu(id, title, parent) values(19, ' 19',5);
insert into tb_menu(id, title, parent) values(20, ' 20',5);
--
insert into tb_menu(id, title, parent) values(21, ' 21',6);
insert into tb_menu(id, title, parent) values(22, ' 22',6);
insert into tb_menu(id, title, parent) values(23, ' 23',7);
insert into tb_menu(id, title, parent) values(24, ' 24',7);
insert into tb_menu(id, title, parent) values(25, ' 25',8);
insert into tb_menu(id, title, parent) values(26, ' 26',9);
insert into tb_menu(id, title, parent) values(27, ' 27',10);
insert into tb_menu(id, title, parent) values(28, ' 28',11);
insert into tb_menu(id, title, parent) values(29, ' 29',12);
insert into tb_menu(id, title, parent) values(30, ' 30',13);
insert into tb_menu(id, title, parent) values(31, ' 31',14);
insert into tb_menu(id, title, parent) values(32, ' 32',15);
insert into tb_menu(id, title, parent) values(33, ' 33',16);
insert into tb_menu(id, title, parent) values(34, ' 34',17);
insert into tb_menu(id, title, parent) values(35, ' 35',18);
insert into tb_menu(id, title, parent) values(36, ' 36',19);
insert into tb_menu(id, title, parent) values(37, ' 37',20);
--
insert into tb_menu(id, title, parent) values(38, ' 38',21);
insert into tb_menu(id, title, parent) values(39, ' 39',22);
insert into tb_menu(id, title, parent) values(40, ' 40',23);
insert into tb_menu(id, title, parent) values(41, ' 41',24);
insert into tb_menu(id, title, parent) values(42, ' 42',25);
insert into tb_menu(id, title, parent) values(43, ' 43',26);
insert into tb_menu(id, title, parent) values(44, ' 44',27);
insert into tb_menu(id, title, parent) values(45, ' 45',28);
insert into tb_menu(id, title, parent) values(46, ' 46',28);
insert into tb_menu(id, title, parent) values(47, ' 47',29);
insert into tb_menu(id, title, parent) values(48, ' 48',30);
insert into tb_menu(id, title, parent) values(49, ' 49',31);
insert into tb_menu(id, title, parent) values(50, ' 50',31);
commit;
select * from tb_menu;
parent 필드 는 상위 id 를 저장 합 니 다. 최상 위 부모 노드 라면 이 parent 는 null (한 마디 보충 해 야 합 니 다. 처음에 이렇게 디자인 했 지만 지금 은 표 에 null 기록 이 있 는 것 이 좋 습 니 다. 이것 은 전체 텍스트 스 캔 을 일 으 킬 수 있 습 니 다. 0 으로 바 꾸 는 것 을 권장 합 니 다).2. 나무 조작 우 리 는 가장 기본 적 인 조작 에서 나무 조회 에서 흔히 볼 수 있 는 조작 을 점차적으로 열거 하고 모든 조회 한 노드 는 가족 중의 세대 로 예 를 들 면.1) 트 리 의 모든 최상 위 부모 노드 (세대 가 가장 긴 사람) 를 찾 습 니 다.이 트 리 가 디 렉 터 리 구조 라 고 가정 하면 첫 번 째 작업 은 항상 모든 최상 위 노드 를 찾 은 다음 에 이 노드 에 따라 부하 노드 를 찾 습 니 다.
select * from tb_menu m where m.parent is null;
2) 한 노드 의 직속 하위 노드 (모든 아들) 를 찾 습 니 다.직속 하위 노드 를 찾 았 다 면 트 리 로 조회 하지 않 아 도 됩 니 다.select * from tb_menu m where m.parent=1;
3), 한 노드 의 모든 직속 하위 노드 (모든 후대) 를 찾 습 니 다.
select * from tb_menu m start with m.id=1 connect by m.parent=prior m.id;
이것 은 id 가 1 인 노드 아래 의 모든 직속 하위 노드 를 찾 습 니 다. 하위 클래스 와 손자 세대 의 모든 직속 노드 를 포함 합 니 다.
4) 、 한 노드 의 직속 부모 노드 (아버지) 를 찾 습 니 다.노드 의 직속 부모 노드 를 찾 았 다 면 트 리 로 조회 하지 않 아 도 됩 니 다.
select c.id, c.title, p.id parent_id, p.title parent_title
from tb_menu c, tb_menu p
where c.parent=p.id and c.id=6;
5) 한 노드 의 모든 직속 부 노드 (조상) 를 찾 습 니 다.select * from tb_menu m start with m.id=38 connect by prior m.parent=m.id;
여기 서 찾 은 것 은 id 가 1 인 모든 직속 부모 노드 이다. 예 를 들 어 한 사람의 아버지, 할아버지 등 을 찾 는 것 이다.그러나 주의해 야 할 것 은 이 조회 결과 의 순 서 는 먼저 하위 노드 를 열거 한 다음 에 부모 노드 를 열거 하 는 것 이 고 우선 역순 이 라 고 생각 하 는 것 이다.위 에 두 개의 트 리 조회 방식, 세 번 째 문장 과 다섯 번 째 문장 이 열거 되 어 있 는데 이 두 문장 사이 의 차 이 는 prior 키워드 의 위치 가 다 르 기 때문에 조회 방식 이 다르다 는 것 을 결정 했다.parent = prior id 일 때 데이터 베 이 스 는 현재 id 에 따라 parent 와 이 id 가 같은 기록 을 교체 하기 때문에 조회 결 과 는 모든 하위 기록 을 교체 한 것 입 니 다.한편, prior parent = id 일 때 데이터 베 이 스 는 현재 parent 에 따라 현재 parent 와 같은 id 의 기록 을 교체 하기 때문에 조회 한 결 과 는 모든 부모 류 결과 입 니 다.
다음은 일련의 나무 구 조 를 대상 으로 하 는 더욱 깊 은 차원 의 조회 이다. 이곳 의 조 회 는 반드시 가장 좋 은 조회 방식 이 아니 라 그 중의 한 가지 실현 일 수도 있다.
6), 한 노드 의 형제 노드 (친형제) 를 조회 합 니 다.
select * from tb_menu m
where exists (select * from tb_menu m2 where m.parent=m2.parent and m2.id=6)
7) 한 노드 와 같은 등급 의 노드 (족 형제) 를 조회 합 니 다.표 에 등급 필드 를 설정 하면 이러한 조 회 를 할 때 매우 쉬 울 것 입 니 다. 같은 등급 은 그 노드 와 같은 등급 입 니 다. 이 필드 를 사용 하지 않 을 때의 실현 을 보 여 줍 니 다!with tmp as(
select a.*, level leaf
from tb_menu a
start with a.parent is null
connect by a.parent = prior a.id)
select *
from tmp
where leaf = (select leaf from tmp where id = 50);
여기 서 두 가지 기 교 를 사용 합 니 다. 하 나 는 level 을 사용 하여 모든 노드 가 표 에 있 는 등급 을 표시 하 는 것 입 니 다. 그리고 with 문법 으로 등급 이 있 는 임시 표를 모 의 한 것 입 니 다.8) 한 노드 의 부모 노드 의 형제 노드 (큰아버지 와 숙부) 를 조회 합 니 다.
with tmp as(
select tb_menu.*, level lev
from tb_menu
start with parent is null
connect by parent = prior id)
select b.*
from tmp b,(select *
from tmp
where id = 21 and lev = 2) a
where b.lev = 1
union all
select *
from tmp
where parent = (select distinct x.id
from tmp x, --
tmp y, --
(select *
from tmp
where id = 21 and lev > 2) z --
where y.id = z.parent and x.id = y.parent);
이곳 조 회 는 다음 과 같은 몇 단계 로 나 뉜 다.
우선 7 번 째 와 마찬가지 로 모든 시 계 를 임시 표 에 등급 을 더 합 니 다.
그 다음으로 등급 에 따라 몇 가지 유형 이 있 는 지 판단 한다. 상기 글 에서 예 를 들 면 세 가지 상황 이 있다.
(1) 현재 노드 는 최고급 노드, 즉 조 회 된 lev 값 이 1 이면 상급 노드 가 없고 고려 하지 않 습 니 다.
(2) 현재 노드 는 2 급 노드 이 고 조회 한 lev 값 은 2 이 므 로 lev 등급 이 1 인 것 이 바로 상급 노드 의 형제 노드 이다.
(3) 다른 상황 은 3 과 이상 의 등급 이다. 그러면 상사 의 상급 노드 (할아버지) 를 조회 한 다음 에 할아버지 의 하급 노드 가 모두 이 노드 에 속 하 는 상급 노드 의 형제 노드 라 고 판단 해 야 한다.
마지막 으로 유 니 온 을 이용 해 조회 한 결 과 를 결합 해 결과 집 을 만 드 는 것 이다.
9) 한 노드 의 부모 노드 의 동급 노드 (족 숙) 를 조회 합 니 다.
이것 은 사실 일곱 번 째 상황 과 같다.
with tmp as(
select a.*, level leaf
from tb_menu a
start with a.parent is null
connect by a.parent = prior a.id)
select *
from tmp
where leaf = (select leaf from tmp where id = 6) - 1;
기본적으로 흔히 볼 수 있 는 조회 가 안에 있 고 흔 하지 않 은 것 도 일부 있다.그 중에서 조회 의 내용 은 모두 노드 의 기본 정보 이 고 모두 데이터 시트 의 기본 필드 이지 만 트 리 조회 에서 특별한 수요 가 있 고 조회 데 이 터 를 처리 한 것 으로 흔히 볼 수 있 는 것 은 트 리 경로 등 을 포함한다.하나의 개념 을 보충 하면 데이터 베이스 에 있어 뿌리 노드 는 반드시 데이터 베이스 에서 디자인 한 최고급 노드 가 아니 라 데이터 베이스 에 있어 뿌리 노드 는 start with 가 시작 하 는 곳 이다.아래 열거 한 것 은 나무 와 관련 된 특수 한 요구 사항 이다.
10) 이름 은 이름 의 모든 경 로 를 표시 해 야 합 니 다.여기 서 흔히 볼 수 있 는 두 가지 상황 이 있 습 니 다. 하 나 는 현재 노드 의 이름 (또는 다른 속성) 까지 최상 위 목록 에서 보 여 주 는 것 입 니 다.하 나 는 현재 노드 에서 최상 위 노드 의 이름 (또는 다른 속성) 까지 보 여 줍 니 다.예 를 들 어 국내의 습관 은 성에 서 시작 하여 시, 현, 주민 위원회 에 가 는 것 이 고 외국 의 습관 은 정반 대 이다. )。 상단 부터:
select sys_connect_by_path (title, '/')
from tb_menu
where id = 50
start with parent is null
connect by parent = prior id;
현재 노드 부터:select sys_connect_by_path (title, '/')
from tb_menu
start with id = 50
connect by prior parent = id;
여기 서 나 는 또 불평 을 해 야 한다. Oacle 은 sys connect by path 함수 만 제공 하고 문자열 의 연결 순 서 를 잊 어 버 렸 다. 위의 예 에서 첫 번 째 sql 은 루트 노드 부터 옮 겨 다 니 는 것 이 고, 두 번 째 sql 은 현재 노드 를 직접 찾 는 것 이다. 효율 적 으로 는 천차만별 이다. 더 중요 한 것 은 첫 번 째 sql 은 하나의 노드 만 선택 할 수 있 고, 두 번 째 sql 은 현재 노드 만 선택 할 수 있다 는 것 이다.두 sql 은 나무 하 나 를 옮 겨 다 녔 습 니 다. 다시 ps.sys connect by path 함 수 는 start with 가 시 작 된 곳 부터 옮 겨 다 니 며 옮 겨 다 니 는 노드 를 기록 하 는 것 입 니 다. start with 가 시 작 된 곳 은 루트 노드 로 간주 되 고 옮 겨 다 니 는 경 로 를 함수 의 구분자 에 따라 새로운 문자열 을 구성 하 는 기능 이 강 합 니 다.
11) 현재 노드 의 루트 노드 를 보 여 줍 니 다.
앞에서 말 했 듯 이 뿌리 노드 는 start with 가 시작 하 는 곳 입 니 다.
select connect_by_root title, tb_menu.*
from tb_menu
start with id = 50
connect by prior parent = id;
connect by root 함 수 는 열 앞 에 사용 되 고 현재 노드 의 뿌리 노드 의 내용 을 기록 합 니 다.12) 현재 노드 가 잎 인지 보 여 줍 니 다.
이것 은 비교적 흔히 볼 수 있 습 니 다. 특히 동적 디 렉 터 리 에서 발 견 된 내용 이 하급 노드 가 있 는 지 여 부 를 알 아 낼 때 이 함 수 는 매우 적 용 됩 니 다.
select connect_by_isleaf, tb_menu.*
from tb_menu
start with parent is null
connect by parent = prior id;
connect by isleaf 함 수 는 현재 노드 에 하급 노드 가 포함 되 어 있 는 지 판단 하 는 데 사 용 됩 니 다. 포함 되 어 있 으 면 잎 노드 가 아니 라 여 기 는 0 으로 돌아 갑 니 다. 반대로 하급 노드 가 포함 되 어 있 지 않 으 면 여 기 는 1 로 돌아 갑 니 다.이로써 Oacle 트 리 조 회 는 기본적으로 끝 났 습 니 다. 이상 의 예 에서 데 이 터 는 해 본 프로젝트 에 사 용 된 데이터 입 니 다. 안의 내용 이 이해 하기 어 려 울 수 있 기 때문에 모두 새로운 예 로 논술 합 니 다. 상기 모든 sql 은 본 컴퓨터 에서 테스트 를 통과 하고 해당 하 는 기능 을 실현 할 수 있 지만 이런 문 제 를 해결 하 는 가장 좋 은 방안 이 라 고 보장 할 수 없습니다.(8 조 와 같이 저장 프로 세 스 로 뚜렷하게 쓰 는 것 이 좋 습 니 다).
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
activemq 5.5 의 입문 은 설치, 시작, 데이터베이스 지속 화 를 포함한다Apache ActiveMQ 5.5.0 은 주로 유지보수 버 전 으로 130 개가 넘 는 문 제 를 복 구 했 으 며 대부분 bug 와 개선 이 었 다. Improved performance for offline d...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.