Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.04.19;
Скачать: CL | DM;

Вниз

По умолчанию Рекурсивный запрос к БД - не могу сообразить как   Найти похожие ветки 

 
frippy   (2008-08-21 21:50) [0]

есть список людей, с именами, адресами и т.д.
У каждой записи есть свой ID - генерится сервером (Interbase)
У некоторых людей в списке есть "подчинённые" - они получают свой ID, но ещё и номер "главного".
В итоге таблица получается "деревом" - у каждого подчинённого могут ещё быть люди в подчинении.
Когда выбираем "самого главного" - видим весь список людей.
Когда выбираем одного из подчинённых - видим список его подчинённых И подчинённых этого подчинённого.
Что не понимаю как сделать - вывести всех подчинённых выбранного подчинённого "вглубь"
Может я немонго сумбурно объяснил, наверное, но суть такова - выбрав на 1-м уровне я должен видеть все уровни вглубь (не важно сколько их),
выбрав 2-й уровень я должен увидеть всех на 3-м, 4-м и т.д. уровнях.
Посмотреть подчинённых без "рекурсии вглубь" - делается на ура и легко, а вот как дальше - не пойму.
Пишется всё на Delphi2006 + IB7


 
stas ©   (2008-08-21 22:01) [1]

Нужно объединить таблицу саму с собой столько раз сколько вложенностей, либо рекурсия либо цикл.
На работе пример есть на MSSQL, завтра скину.
Смысл такой объединяешь таблицу саму с сабой результат списываешь во временную таблицу, а потом в цикле объединяешь временную таблицу саму с собой и списываешь в нее же результат,  пока результат небудет NULL.


 
Евгений Р.   (2008-08-21 22:04) [2]

for
  select idf
  from tbl
  where idfGlavn=:idf into :idfOut do Begin
  suspend;
  for select idf
       from ЭтаПроцедура(:idfOut) into :idfOut do suspend;
End;


 
stas ©   (2008-08-21 22:04) [3]

тут посмотри:
http://delphimaster.net/view/3-1213899571/


 
frippy   (2008-08-21 22:06) [4]

Объединять саму с собой таблицу это хорошо, но...у меня 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;

это работает на любую "глубину" но только для одного человека и только его подчинённых.


 
frippy   (2008-08-21 22:14) [5]

2stas - временная таблица не годится, у меня 10 человек будет добавлять записи и делать выборки одновременно

Евгений Р. - а можно поподробней, если не затруднит...?


 
Евгений Р.   (2008-08-21 22:40) [6]

tbl - таблица с людьми
idf - идф. человека
idfGlavn-идф.начальника

Хранимая процедура
вх.параметр - Idf
выходной - IdfOut

результат - список idf всех подчиненных

внешний цикл - выбираем и выдаем всех подчиненных предыдущего уровня
внутренний цикл - рекурсивно выдаем для каждого подчиненного всех подчиненных


 
frippy   (2008-08-21 22:44) [7]

идущий да обрящет....

думаю что удалось побороть, вот статья:
http://www.az-design.ru/Support/DataBase/Heiven13.shtml

конкретно - делаем процедуру и запрос

осталось проверить в деле......


 
Prohodil Mimo ©   (2008-08-21 23:23) [8]

ещё на ibase.ru есть статьи.
Но я предпочитаю на клиенте дерево генерить.


 
stas ©   (2008-08-22 08:56) [9]

frippy   (21.08.08 22:06) [4]
Да хоть 100. Вы же придумали такую структуру - не я.
Тяжеловато конечно будет работать рекурсия. Я выше ссылку давал там я описывал как триггерами наполнять постоянную таблицу в момент заполнения вашей таблицы.


 
место   (2008-08-22 13:42) [10]

нет возможности проверить, но по идее так можно получить полный список

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


 
stas ©   (2008-08-22 15:11) [11]

место   (22.08.08 13:42) [10]
Нет это только 2-й уровень


 
Труп Васи Доброго ©   (2008-08-22 16:44) [12]

вот тебе процедура готовая и работающая

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 короче всё как у тебя.


 
Vlad Oshin ©   (2008-08-22 17:14) [13]

http://yandex.ru/yandsearch?&text=%D1%81%D0%B2%D0%BE%D0%B8%D0%BC%D0%B8%20%D1%80%D1%83%D0%BA%D0%B0%D0%BC%D0%B8%20%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2%D0%B0%20delphi&msp=1



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

Текущий архив: 2009.04.19;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.018 c
15-1235208148
Индеец
2009-02-21 12:22
2009.04.19
Компоненты для сжатия данных


2-1235711956
nastya
2009-02-27 08:19
2009.04.19
Злополучная лямда


15-1235057883
Бурато
2009-02-19 18:38
2009.04.19
Алгебра


15-1234992602
Юрий
2009-02-19 00:30
2009.04.19
С днем рождения ! 19 февраля 2009 четверг


11-1174764339
Dmitriy___
2007-03-24 22:25
2009.04.19
Перехват ресайза колонок ListView