Всем привет!
Помогите пожалуйста решить задачу. Существует , база со структурой бинарного дерева. Даны данные о всех элементах (ID ) и данные о их родителей (parentID). Задача сделать функцию, которая покажет всех детей - конкретного элементов и укажет на каком уровне находятся дети от данного элемента. И данная функция пройдет по всем элементам.
Дана таблица domains
ID integer, - Ид элемента
parentID integer - ИД элемента предка
Входные данные
Dannie s tablici Domains
ID; ParentID
1;Null
101;1
111;101
112;101
166;1
216;166
209;166
300;216
301;216
410;300
411;300
Результате -
1;101; 1
1;166;1
1;111;2
1;112;2
101;111;1
101;112;1
1;216;2
1;209;2
1;300;3
1;301;3
1;410;4
1;411;4
166;216;1
166;209;1
166;300;2
166;301;2
166;410;3
166;411;3
216;300;1
216;301;1
216;410;2
216;411;2
300;410;1
300;411;1
ID integer - Ид элемента ,
relativeID integer - Ид - ребенка
level integer - уровень - ( на каком уровне находится ребенок (relativeID ) от родителя (ID) вниз
Заранее спасибо.
Написал функцию
CREATE OR REPLACE FUNCTION get_domain_chl(pid integer) RETURNS SETOF mt AS $BODY$ DECLARE rec mt%rowtype; BEGIN FOR rec IN SELECT id, parentid FROM domains_test WHERE parentid = pid LOOP RAISE NOTICE 'BBBBB %', rec; RETURN NEXT rec; RETURN query SELECT id, parentid FROM get_domain_chl( rec.id ); END LOOP; RETURN; END $BODY$ LANGUAGE plpgsql VOLATILE COST 100 ROWS 1000;
Пробовал по разному добавить счетчик уровней - не получается
CREATE OR REPLACE FUNCTION get_domain_chl(pid integer) RETURNS SETOF mt AS $BODY$ DECLARE rec mt%rowtype; lvl integer; BEGIN lvl :=1 FOR rec IN SELECT id, parentid FROM domains_test WHERE parentid = pid LOOP rec.lvl:=lvl + 1 RAISE NOTICE 'BBBBB %', rec; RETURN NEXT rec; RETURN query SELECT id, parentid FROM get_domain_chl( rec.id ); END LOOP; RETURN; END $BODY$ LANGUAGE plpgsql VOLATILE COST 100 ROWS 1000;
Помогите пожалуйста.
Откровенно лень вникать. Могу
Откровенно лень вникать. Могу лишь направить в сторону вот этой страницы мануала, где как раз рассматриваются рекурсивные запросы:
http://postgresql.ru.net/manual/queries-with.html
На мой взгляд без рекурсивного запроса вам всё это не развернуть.
Спасибо, я написал
Спасибо за подсказку , я написал функцию
Я сделал функцию иерархическую с вводимой вершиной - с которой функция начнет спускаться вниз.
Но у меня не получается - менять каждый раз вершину с которой снова побежим по дереву. (вершина которая находится на один уровень ниже).
Я делал так:
Текст написанный ниже воспроизведен по памяти без синтаксической проверки, так, как Постгресса у меня на данном компе нету...
Нам потребуются:
временные таблицы- 3 штуки и переменная
u inetger; /*уровень*/
create temporary table body_ /*Результирующая выборка*/
(
id integer,
pid inetger,
sort text,
urov integer
);
create temporary table c_ur( /*Временные для цикла */
id integer,
pid inetger,
sort text,
urov integer
);
create temporary table c_ur1(
id integer,
pid inetger,
sort text,
urov integer
);
заполняем таблицы вершиной дерева:
insert into c_ur(id,pid,urov)
select k.id,k.parentid,1 from domain.test as k
where k.parentid is null;
insert into body_ (id,pid,urov) select k.id,k.parentid,1 from domain.test as k;
u:=1
/*собственно цикл*/
while exists (select l.id from domain.test as l join c_ur on l.parentid=c_ur.id where c_ur.urov=u) loop
insert into body_ (id,pid,urov) select k.id,k.parentid,u+1 from domain.test as k join c_ur as c on k.parentid=c.id where c.urov=u;
delete from c_ur1;
insert into c_ur1 (id,pid,urov) select k.id,k.parentid,u+1 from domain.test as k join c_ur as c on k.parentid=c.id where c.urov=u;
delete from c_ur;
insert into c_ur select * from c_ur1;
u=u+1;
end loop;
;
Далее выбираем все из body и кормим return.
Как-то так. Еще раз оговорюсь, что в запросе наверное много ошибок, но чтобы уловить суть, я думаю, этого хватит.
Спасибо - попробую
Спасибо - попробую