Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2003.04.17;
Скачать: [xml.tar.bz2];

Вниз

Копирование иерархий(поддеревьев в дереве)   Найти похожие ветки 

 
AlexandrN   (2003-03-26 09:16) [0]

Привет всем...
Короче...
Есть иерархическая структура представленная как PARENT - CHILD, в таблице вида:
ID | Parent_ID | Level | Other
, где ID - идентификатор объекта;
Parent_ID - ссылка на ID;
Level - уровень в дереве;

Если кто знает или подозревает,
Как можно скопировать часть поддерева и вставить его в новое место, причём именно копирование(как в проводнике с папками), то немогли бы вы поделиться как всётаки это делается, хотелось бы всётаки увидеть как это делаетсь на практике, а не в теории.


 
Mike_Goblin   (2003-03-26 09:21) [1]

На практике это делается с помощью рекурсивных вызовов процедуры копирования элемента дерева.


 
Соловьев   (2003-03-26 09:31) [2]

а можно взять и присвоить друго просто родителя, вот и все.


 
Sergey13   (2003-03-26 09:34) [3]

2AlexandrN (26.03.03 09:16)
Это вопрос не простой даже для Оракула(где есть "деревянные" запросы). Основная сложность состоит в том, что надо по ходу дела менять ID & Parent_ID на новые, но сохранять при этом связи. Я делал это примерно так (на Оракле). Вытаскивал в память все узлы и сразу(в запросе) генерил им новые Id-шники. Потом бегал по этому "массиву" циклами и заменял старые значения ID & Parent_ID на новые. Потом уже писал в таблицу.


 
Polevi   (2003-03-26 09:35) [4]

2Соловьев © (26.03.03 09:31)
это будет не копирование а перемещение


 
Соловьев   (2003-03-26 09:45) [5]

сорри не догнал сначала.


 
AlexandrN   (2003-03-26 10:12) [6]

Да подкинул ч не лёгкую задачку....??????
Но всё же где - же вы умельцы, которые моглибы поделиться, хотябы самой тупой реализацией (SP or Func)!?


 
zacho   (2003-03-26 10:31) [7]


> AlexandrN (26.03.03 10:12)

Какая СУБД ?


 
kaif   (2003-03-26 10:33) [8]

Для работы с деревьями в IB я написал 2 процедуры.
1. Одна возвращает ID всех предков данного узла, включая его самого.(простой запрос предка в цикле, пока ID предка найден + SUSPEND)
2. Вторая процедура объединяет всю таблицу дерева с результатом работы первой процедуры и возвращает все пары
ID, CHILD_ID с помощью SUSPEND. В результате я получаю виртуальную таблицу, в которой каждому ID сопоставлены все потомки всех уровней для данного ID.

Все дольнейшие операции работы с деревом тогода не представляют труда. Например, чтобы выбрать всех потомков данного ID мне достаточно сделать простой SELECT из второй процедуры с условием ID = что-то.

Соответственно subj.
Я бы просто взял результат такого селекта, объединил еще раз с исходной таблицей, чтобы получить CHILD_ID, PARENT_ID, дал бы смещение, равное общему количеству COUNT(*) строк такого набора обоим полям и одной командой вставил бы в ту же таблицу.
INSERT INTO T1
SELECT P2.CHILD_ID + :offset, T1.PARENT_ID + :offset
FROM PROCEDURE2 P2, T1 WHERE P2.CHILD_ID = T1.ID;

Надеюсь, объяснил понятно.


 
Соловьев   (2003-03-26 10:38) [9]

Я вот писал процедуру для поиска пути от родителя до корня.
думаю переделать ее под твою задачу не займет много времени:

CREATE PROCEDURE GETPARENTS (
ID_PROF INTEGER)
RETURNS (
NAME VARCHAR (1000))
AS
DECLARE VARIABLE PATH VARCHAR(1000);
DECLARE VARIABLE PATH_TEMP VARCHAR(1000);
DECLARE VARIABLE OID INTEGER;
DECLARE VARIABLE ID INTEGER;
BEGIN

FOR
SELECT ID_OPERATION
FROM TYPE_OPERATION
WHERE CHILD_CNT=0 AND PROFESSION_ID=:ID_PROF
INTO :ID
DO
BEGIN
PATH_TEMP = " ";
WHILE (:ID > 0) DO /* ИЩЕМ ДО КОРНЯ */
BEGIN
SELECT O.PARENT_ID, O.NAME_OPERATION
FROM TYPE_OPERATION O
WHERE O.ID_OPERATION = :ID
INTO :OID, :PATH;
ID = :OID; /* КОД РОДИТЕЛЯ ДЛЯ СЛЕДУЮЩЕЙ ВЫБОРКИ */
PATH_TEMP = :PATH||"|"||PATH_TEMP;
END
NAME = :PATH_TEMP;
SUSPEND;
END
END


 
kaif   (2003-03-26 10:39) [10]

Точнее
INSERT INTO T1
SELECT P2.CHILD_ID + :offset, T1.PARENT_ID + :offset
FROM PROCEDURE2 P2, T1 WHERE P2.CHILD_ID = T1.ID AND P2.ID = :id;
где параметр :id - "копируемая" папка.




 
Соловьев   (2003-03-26 10:42) [11]

Забыл написать, что это для IB и FB


 
kaif   (2003-03-26 10:52) [12]

2 Соловьев © (26.03.03 10:38)
Да, Вы правы. Именно так можно построить первую процедуру. Только возвращать надо не текст пути, а просто PARENT_ID и ID всех обойденных пунктов.
Затем объединив в запросе такой набор по PARENT_ID с исходной таблицей получаем все пары старший-любой младший. А затем любая, самая невероятная задача работы с деревом решается как правило одним простым селектом.


 
Соловьев   (2003-03-26 10:54) [13]

2 kaif ©
я же и написал, что надо будет переделать чутка...


 
AlexandrN   (2003-03-26 11:26) [14]

Ответ на вопрос про СУБД: Sybase SQL Anywhere 7.


 
kaif   (2003-03-26 11:34) [15]

Если в Sybase нет аналога команде SUSPEND InterBase-а, то мой метод не будет работать и придется писать обход дерева в лоб в каком-нибудь курсоре.


 
AlexandrN   (2003-03-26 11:40) [16]

Да Sybase не знает про SUSPEND...


 
Sergey13   (2003-03-26 11:54) [17]

2AlexandrN (26.03.03 09:16)
А какая разница SUSPEND... не SUSPEND...
Смысл то одинаковый. Выташить искомое дерево, переназначить ID и вставить назад. Или тебе готовую процедуру хочется? Сейчас то ты с деревом как работаешь? Или не работаешь вообще?


 
AlexandrN   (2003-03-26 12:13) [18]

2Sergey13:
Дерево для копирования получаю просто за один запрос, за счёт хранения иерархий элементов дерева в виде:
.ROOT_ID.ID.ID.ID. ....
, где ROOT_ID - корень всего дерева(АЛЯ диски в проводнике);
ID - дочерние элементы;

Также стоит тригер на добавление новых элементов, который автоматически расчитывает уровень нового элемента в дереве, и строит иерархию для этого элемента.

На счёт готовой процедуры.......!
Сам я неселён в написании этих самых ханимых процедур и функции(ПЛОХОВАТО - САМ ПОНИМАЮ) поэтому и обратился к обществу с таким вопросом, в надежде, что ктото делал уже подобное и ему несоставит большого труда поделиться реализацией.

P.S.
Спасибо всем ктоб что либо предлагает...


 
kaif   (2003-03-26 12:27) [19]

Самое главное это может ли Sybase, как это делает IB, с выходным набором, возвращаемым процедурой обращаться как с простой таблицей?
То есть можно ли в Sybase написать
SELECT * FROM MYPROCEDURE ?


 
AlexandrN   (2003-03-26 13:11) [20]

Походу дела нет...


 
Sergey13   (2003-03-27 10:11) [21]

2AlexandrN (26.03.03 12:13)
>Дерево для копирования получаю просто за один запрос, за счёт >хранения иерархий элементов дерева в виде:
>.ROOT_ID.ID.ID.ID. ....
>, где ROOT_ID - корень всего дерева(АЛЯ диски в проводнике);
> ID - дочерние элементы;
Т.е. одной строкой получаешь что ли? Тогда это не дерево, а список дочерних узлов или конкретная ветка дерева. Если это ветка (т.е. каждый следующий ID это потомок предыдущего и наоборот) и надо скопировать именно ее то какие затруднения у тебя это вызывает. Схема твоей процедуры примерно такая будет. С Sybase не знаком, поэтому своими словами:

получаешь свою цепочку ID, запоминаешь ее
В цикле по цепочке

1.генеришь новый ID, запоминаешь его
2.делаешь insert где ID это только что сгенеренный, Parent_id запомненый предыдущий(для первой записи NULL или Id того места куда вставляешь ветку), остальные поля старые

Примерно так. С конкретной реализацией - сам.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2003.04.17;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.009 c
3-54403
me2
2003-04-01 11:30
2003.04.17
Как снести IB DescTop Edition


8-54746
darkbear
2003-01-14 11:59
2003.04.17
GDI+: Ширина строки


14-54831
Думкин
2003-04-01 06:15
2003.04.17
День птиц, дураков и математиков


7-54904
Gero-man
2003-02-23 12:17
2003.04.17
Отлов обращений к файлу


3-54469
Sewix
2003-03-29 09:21
2003.04.17
Кто нибудь ставил oracle на Win 98





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский