drop table test_table; CREATE TABLE `TEST_TABLE` ( |
2. 테이블 데이터 추가
insert into TEST_TABLE(p_id, nm) values ( 0, '왕'); insert into TEST_TABLE(p_id, nm) values ( 1, '왕자'); insert into TEST_TABLE(p_id, nm) values ( 1, '공주'); insert into TEST_TABLE(p_id, nm) values ( 2, '왕자아들'); insert into TEST_TABLE(p_id, nm) values ( 2, '왕자딸'); insert into TEST_TABLE(p_id, nm) values ( 3, '공주아들'); insert into TEST_TABLE(p_id, nm) values ( 6, '공주아들의 딸'); insert into TEST_TABLE(p_id, nm) values ( 1, '배다른 형제'); |
3. Function 생성
DROP FUNCTION IF EXISTS get_lvl_test_table; DELIMITER $$ BEGIN SET v_parent = @id; IF @id IS NULL THEN LOOP IF @id IS NOT NULL OR v_parent = @start_with THEN SET @level := @level - 1; SELECT id, p_id |
4. 실행
SELECT |
==============================================================================================================
==============================================================================================================
출처 : http://www.lovelgw.com/Blog/275
http://blog.naver.com/tyboss/70081682199
장점 : 무한 계층 가능
단점 : 구현이 어렵다.
Nested Set Model (중첩 설정 모델)
Nested Set Model 을 이용하여 계층적 구조를 표현해보도록 하겠습니다. 아래 그림은 보라색 화살표 방향으로 정렬이 됩니다. 모든 노드의 왼쪽 값을 가지고 정렬을 하고 있습니다.
그림 1 - Nested Set Model 정렬
위 그림은 부모 분류가 자식 분류를 포함하도록 설계가 했습니다. 1개의 분류에는 자식을 포함 할 수 있는 범위가 들어있습니다. 즉 1개의 자식을 추가하기 위해서는 해당 자식노드를 포함하는 상위 레벨의 모든 부모에 값을 변경해주어야 합니다. 그리고 탐색순서는 자식 노드의 범위 값 중 작은 범위의 값(Left point)를 가지고 정렬을 하게 됩니다.
반대로 자식 노드의 삭제의 경우에 해당 자식노드를 삭제 하고 포함한 부모와 자식을 포함하지 않은 그외 노드에 대한값도 삭제된 자식 노드의 범위만큼 범위를 수정해주어야 합니다.
위 방식으로 테이블을 만들어 보겠습니다.
CREATE TABLE NestedSetMenu |
테이블을 생성하고 데이터를 넣습니다. 이후 삽입되는 데이터의 경우 부모의 값을 이용하여 하위로 들어가게 되고 구조상 동일 레벨의 가장 오른쪽(그림 1 표현에서)에 데이터가 삽입됩니다.
삽입 되는 과정 및 구조 설명입니다.
1. 선택한 부모의 우측포인트를 구합니다.
2. Node 가 들어갈 자리를 마련하기 위해 우측 값이 부모의 우측 값 보다 크거나 같은모든 값에 +2를 해줍니다.
3. Node 가 들어갈 자리를 마련하기 위해 좌측 값이 부모의 우측 값 보다 큰 모든 값을 + 2를 해줍니다.
4. 노드를 입력합니다. (좌 부모 우측값, 우 = 부모우측값 + 1)
삭제 되는 과정 및 구조 설명입니다.
1. 삭제할 노드의 왼쪽 , 오른쪽 값을 구합니다.
2. 삭제할 노드의 범위를 구합니다. ((오른쪽 - 왼쪽) + 1)
3. 노드를 삭제 합니다.
4. 노드의 오른쪽 범위와 왼쪽 범위보다 큰 값(왼쪽 ,오른쪽)들을 삭제 노드의 범위 만큼 빼줍니다.
노드가 이동되는 구조 설명입니다.
1. 옮겨질 노드의 왼쪽, 오른쪽 , 범위 값을 구합니다.
2. 옮겨질 노드의 값을 초기값 (최상단 왼쪽 노드의 좌측값을 1로 시작해 초기화 시킵니다.)
3. 옮겨질 노드의 상태값을 변경합니다.(그외 노드를 수정시 변경되는것을 방지합니다.)
4. 그외 노드의 Left, Right 값을 이동할 노드의 범위 만큼 빼줍니다. (삭제와 동일)
5. 대상 노드의 정보를 구합니다.
6. 대상 노드에 옮겨질 노드가 들어올 자리를 마련하기 위해 Left, Right 값을 옮겨질 노드의 범위만큼 더해줍니다. (Right 가 대상 노드의 Right 와 같거나 큰 노드, Left 가 Right보다 큰 노드)
7. 옮겨질 노드를 대상 노드의 위치로 옮기기 위해 대상 노드의 Right 값에서 1을 뺀만큼 Left, Right 에 더해줍니다.
노드의 순위를 변경하는 구조 설명입니다.
1. 순서의 변경은 대상노드가 왼쪽에서 오른쪽으로 이동형식으로 이루어집니다. (노드의 우선순위 산정)
2. 왼쪽 노드의 정보를 구합니다.
3. 왼쪽 노드의 Left, Right 를 오른쪽 노드와 왼쪽노드의 거리(오른쪽 노드 Right - 왼쪽노드의 Right) 를 더해줍니다.
4. 그외 노드에서 Left 가 왼쪽노드의 Right, 오른쪽 노드의 Right 범위에 해당하는 노드들의 Left, Right 값을 이동할 노드의 범위 만큼 빼줍니다.
위 방식으로 노드의 추가, 삭제 , 이동, 순위 변경이 가능합니다. 시간이 나는대로 도표를 그려 첨부해야겟네요 ^^ 말로 하자니 조금 복잡한 면이 있어 보입니다 ^^
아래 프로시져는 위 노드의 계층형 구조를 보여주는 프로시져 입니다. ^^
DROP PROCEDURE IF EXISTS showNode; DELIMITER %% CREATE PROCEDURE showNode() BEGIN SELECT Node.nSeq, CONCAT(REPEAT("\t", (COUNT(Parent.nSeq) - 1) ), Node.strName) as strName, Node.nLeft, Node.nRight FROM NestedSetMenu AS Node, NestedSetMenu AS Parent WHERE Node.nLeft BETWEEN Parent.nLeft AND Parent.nRight GROUP BY Node.nSeq ORDER By Node.nLeft; END %% DELIMITER ;
|
위 방식으로 카테고리, 메뉴등을 작업하면 메뉴의 순위 변경이나 부모 노드의 삭제로 인해 자식노드가 부모를 잃어버리는 경우를 피할 수 있습니다. 또한 계층형 출력이나 , 관리등에서 많은 잇점을 가지고 있습니다. (게시판등에서 이용하는것은 비효율적이겠죠? 업데이트시 상당한 부하가 걸릴테니까요 ^^)
노드의 변경에 따른 도표는 지금 작성중이어서 그림으로 차차 추가 하도록 하겠습니다.
부록 : 예제 테이블에서 사용할 수 있는 프로시져입니다. 한번 테스트 해보세요~ ^^ 실제 사용에는 약간의 기능 추가및 예외 처리가 필요합니다. 아래 예제 사용시 발생되는 문제는 책임지지 않습니다. Nested Set Model 을 설명하기 위해 예제로 작성해본 프로시져입니다 ^^
|
==============================================================================================================
==============================================================================================================
출처 : http://blog.daum.net/neolinux/64
장점 : 쉽다.
단점 : 무한 계층 불가
drop table category; CREATE TABLE category( INSERT INTO category
SELECT t1.name AS lev1, t2.name as lev2, |
-- 카테고리 테이블을 작성한다. DROP TABLE IF EXISTS category ;
SELECT * FROM category ORDER BY category_id;
-- 레벨의 마지막 leaf node 만을 조회
|
출처 : http://tyboss.tistory.com/entry/MySQL-%EC%9E%AC%EA%B7%80%EC%BF%BC%EB%A6%AC-recursive
'IT > MySQL' 카테고리의 다른 글
백업 및 복원 (0) | 2015.04.03 |
---|---|
스케쥴 관련 (0) | 2015.04.02 |
MySQL에서의 RowNum 사용 (0) | 2015.02.13 |
임시테이블 사용 및 변수(DECLARE) 사용 (0) | 2015.02.13 |
MySQL 수학 함수 정리 (0) | 2015.02.11 |