Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Перемещение узла в дереве (NestedSets) / 4 сообщений из 4, страница 1 из 1
18.07.2008, 12:24
    #35438906
ss25
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перемещение узла в дереве (NestedSets)
Есть дерево

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
id code name lft rgt level 
 588  [Root]   1   34   0  
 589   0  Загальний відді  2   21   1  
 590   00  Загальні питання науки і культур  3   6   2  
 591   004  Комп'ютерна наука і технологі 4 5 3 
592 01 Бібліографія і бібліографічні покажчики. Каталог 7 8 2 
593 02 Бібліотечна справ 9 10 2 
594 030 Довідкові видання загального тип 11 12 2 
595 050 Серійні публікації. Періодик 13 14 2 
596 06 Організація та інші типи об'єднань (співробітництва  15   16   2  
 597   070  Газети. Прес  17   18   2  
 598   09  Рукописи. раритети і рідкісні книг  19   20   2  
 604   2  Релігія. Теологі  22   31   1  
 772   9  Географія. Біографії. Історі  23   30   2  
 773   91  Географія. Географічні дослідження землі та окремих країн. Подорожні. Регіональна географі  24   25   3  
 774   929  Біографічні та подібні дослідженн  26   27   3  
 775   93  Історі  28   29   3  
 755   7  Мистецтво. Декоративне-прикладне мистецтво. Ігри. Спор  32   33   1  

Функция перемещения узла
SELECT library.udc_move_node(772, 604, 0);
772 ИД перемещаемого
604 ИД куда переносится

при перемещении не правильно расчитывается правый ключ помогите разобраться вот код функции перемещения
CREATE OR REPLACE FUNCTION "library"."udc_move_node" (integer, integer, integer) RETURNS boolean AS
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
DECLARE

pleft INT4;
pright INT4;
plevel INT4;

nleft INT4;
nright INT4;
nlevel INT4;

aleft INT4;
aright INT4;

treeshift INT4;
leftbound INT4;
rightbound INT4;
cwidth INT4;

leftrangemax INT4;
leftrangemin INT4;
rightrangemax INT4;
rightrangemin INT4;

pid INT4;  -- Ид перемещаемого узла
nid INT4; -- Ид нового родителя
aid INT4; -- Ид после которого будет вставка

BEGIN

pid := $ 1 ;
nid := $ 2 ;
aid := $ 3 ;

IF pid = nid THEN
	RAISE EXCEPTION ''Cannot move: entries are identical'';
END IF;

-- Получение данных о перемещаемой ветке
SELECT lft, rgt, level FROM library.udc WHERE id = pid INTO pleft, pright, plevel;
IF NOT FOUND THEN
    RAISE EXCEPTION ''Udc ID % not found'', pid;
END IF;

-- Получение данных о новой одительской ветке
SELECT lft, rgt, level FROM library.udc WHERE id = nid INTO nleft, nright, nlevel;
IF NOT FOUND THEN
    RAISE EXCEPTION ''New Parent Udc ID % not found'', nid;
END IF;

IF aid !=  0  THEN

	-- Получение данных о ветке после которой будет вставка
	SELECT lft, rgt FROM library.udc WHERE id = aid INTO aleft, aright;
	IF NOT FOUND THEN
    	RAISE EXCEPTION ''After Udc ID % not found'', aid;
	END IF;

ELSE
	aright := nleft;
END IF;

IF nleft BETWEEN pleft AND pright THEN
	RAISE EXCEPTION ''Cannot move: first entry contains second'';
END IF;

IF pleft = (nleft +  1 ) THEN
	RAISE EXCEPTION ''No changes need to be made'';
END IF;

IF pleft > nleft THEN

	treeshift := aright - pleft +  1 ;
	leftbound := aright +  1 ;
	rightbound := pleft -  1 ;
	cwidth := pright - pleft +  1 ;

	leftrangemax := pright;
	leftrangemin := nleft;
	rightrangemax := pright;
	rightrangemin := nleft;

ELSE

	treeshift := aright - pright;
	leftbound := pright +  1 ;
	rightbound := aright;
	cwidth := pleft - pright -  1 ;
				
	leftrangemax := nleft +  1 ;
	leftrangemin := pleft;
	rightrangemax := nright;
	rightrangemin := pleft;

END IF;

UPDATE library.udc 
	SET level = level + ((nlevel +  1 ) - plevel) 
WHERE	lft >= pleft AND rgt <= pright;

UPDATE library.udc
	SET lft = CASE
		WHEN lft BETWEEN leftbound AND rightbound THEN lft + cwidth
                WHEN lft BETWEEN pleft AND pright THEN lft + treeshift
        ELSE lft END,
				            	
  	    rgt = CASE
                WHEN rgt BETWEEN leftbound AND rightbound THEN rgt + cwidth
                WHEN rgt BETWEEN pleft AND pright THEN pright + treeshift
        ELSE rgt END
				
	WHERE 
	    (lft <= leftrangemax AND lft >= leftrangemin) 
	OR 
	    (rgt >= rightrangemin AND rgt <= rightrangemax);

RETURN true;
END;
...
Рейтинг: 0 / 0
18.07.2008, 23:41
    #35440476
Sad Spirit
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перемещение узла в дереве (NestedSets)
Сам в своё время помучился над этим алгоритмом, всё становится проще, если рассматривать операцию переноса ветки как последовательность операций удаления ветки и добавления ветки.
...
Рейтинг: 0 / 0
20.07.2008, 01:53
    #35441083
Денис Ильин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перемещение узла в дереве (NestedSets)
у меня есть полный набор алгоритмов работы с подобными деревьями.
публиковать публично их я не буду (а жаль, но вот так), перемещение узла (максимально быстрый вариант) - это весьма геморойное занятие.
рекомендую для глубокого понимания вопросов работы с такими деревьями почитать
Джо Селко "SQL для профессионалов"
...
Рейтинг: 0 / 0
21.07.2008, 03:51
    #35441523
tkopets
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Перемещение узла в дереве (NestedSets)
прочитай лучше про ltree
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Перемещение узла в дереве (NestedSets) / 4 сообщений из 4, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]