-
есть список людей, с именами, адресами и т.д. У каждой записи есть свой ID - генерится сервером (Interbase) У некоторых людей в списке есть "подчинённые" - они получают свой ID, но ещё и номер "главного". В итоге таблица получается "деревом" - у каждого подчинённого могут ещё быть люди в подчинении. Когда выбираем "самого главного" - видим весь список людей. Когда выбираем одного из подчинённых - видим список его подчинённых И подчинённых этого подчинённого. Что не понимаю как сделать - вывести всех подчинённых выбранного подчинённого "вглубь" Может я немонго сумбурно объяснил, наверное, но суть такова - выбрав на 1-м уровне я должен видеть все уровни вглубь (не важно сколько их), выбрав 2-й уровень я должен увидеть всех на 3-м, 4-м и т.д. уровнях. Посмотреть подчинённых без "рекурсии вглубь" - делается на ура и легко, а вот как дальше - не пойму. Пишется всё на Delphi2006 + IB7
-
Нужно объединить таблицу саму с собой столько раз сколько вложенностей, либо рекурсия либо цикл. На работе пример есть на MSSQL, завтра скину. Смысл такой объединяешь таблицу саму с сабой результат списываешь во временную таблицу, а потом в цикле объединяешь временную таблицу саму с собой и списываешь в нее же результат, пока результат небудет NULL.
-
for select idf from tbl where idfGlavn=:idf into :idfOut do Begin suspend; for select idf from ЭтаПроцедура(:idfOut) into :idfOut do suspend; End;
-
-
Объединять саму с собой таблицу это хорошо, но...у меня 10 машин будут одновременно делать это. Думаю варинат не приемлем :(
А вот рекурсия-цикл - да, но не могу сообразить как Для одного человека я сделал так:
var number: integer; begin if DBGrid4.SelectedField.AsString<>'' then //если есть человек, чьих подчинённых ищем begin IBQuery3.SQL.Clear; IBQuery3.SQL.Add('select * from list where num='+DBGrid4.SelectedField.AsString); //нашли человека, узнаём кто его "главный" IBQuery3.Open; number:=DBGrid4.SelectedField.AsInteger; IBQuery3.Locate('num',number,[]); IBQuery1.SQL.Clear; IBQuery1.SQL.Add('select * from list where main='''+Inttostr (number)+''''); //нашли всех, у кого главным записан человек с ID=number IBQuery1.Open; end;
это работает на любую "глубину" но только для одного человека и только его подчинённых.
-
2stas - временная таблица не годится, у меня 10 человек будет добавлять записи и делать выборки одновременно
Евгений Р. - а можно поподробней, если не затруднит...?
-
tbl - таблица с людьми idf - идф. человека idfGlavn-идф.начальника
Хранимая процедура вх.параметр - Idf выходной - IdfOut
результат - список idf всех подчиненных
внешний цикл - выбираем и выдаем всех подчиненных предыдущего уровня внутренний цикл - рекурсивно выдаем для каждого подчиненного всех подчиненных
-
-
ещё на ibase.ru есть статьи. Но я предпочитаю на клиенте дерево генерить.
-
frippy (21.08.08 22:06) [4] Да хоть 100. Вы же придумали такую структуру - не я. Тяжеловато конечно будет работать рекурсия. Я выше ссылку давал там я описывал как триггерами наполнять постоянную таблицу в момент заполнения вашей таблицы.
-
нет возможности проверить, но по идее так можно получить полный список
select a.id_people, a.people_name, b.id_people, b.people_name from t_people a, t_people b where a.id_people = b.id_owner order by a.id_people, b.id_people
-
место (22.08.08 13:42) [10] Нет это только 2-й уровень
-
вот тебе процедура готовая и работающая
SET TERM ^ ;
CREATE OR ALTER PROCEDURE ADRESS_SEL_DOWN ( id1 INTEGER) RETURNS ( id INTEGER) AS begin for SELECT id FROM s_adres where s_adres.pid=:id1 into :id DO begin suspend; IF (EXISTS(SELECT id FROM s_adres where s_adres.pid =:id)) THEN BEGIN FOR SELECT id from ADRESS_SEL_DOWN(:id) INTO :id DO SUSPEND; END end
end^
SET TERM ; ^
таблица s_adres в ней ID это ID, а PID это Parent ID короче всё как у тебя.
-
|