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

Вниз

Дерево в БД   Найти похожие ветки 

 
goozman   (2004-05-06 10:12) [0]

Помогите пожалуйста, есть таблица, главные поля (ID, PARENT_ID) по ним строится дерево- по полю ID я могу добратся к самому верхнему родителю, а теперь вопрос помогите создать запрос по которому можно по родителю (самому верхнему) узнать все дочерние его ветки! Очень надеюсь на Вашу помощь!


 
Соловьев ©   (2004-05-06 10:16) [1]


> самому верхнему родителю, а теперь вопрос помогите создать
> запрос по которому можно по родителю (самому верхнему) узнать
> все дочерние его ветки! Очень надеюсь на Вашу помощь!

www.ibase.ru


 
goozman   (2004-05-06 10:19) [2]

Наверное я неправильно выразился, мне надо не количество веток, а все записи с их ID


 
Соловьев ©   (2004-05-06 10:25) [3]


> goozman   (06.05.04 10:19) [2]

там все это есть


 
Курдль ©   (2004-05-06 11:06) [4]

Это не решается запросом (разве что на Оракле).


 
Соловьев ©   (2004-05-06 11:10) [5]


> Курдль ©   (06.05.04 11:06) [4]

ХП


 
Мунька   (2004-05-06 11:13) [6]

Одним запросом не решается. Я строила дерево из таблицы Access - дерево подразделений, находила также предков-потомков, но одним запросом это не решается, если интересно, могу кусок кода поиска потомков кинуть


 
Соловьев ©   (2004-05-06 11:15) [7]


> Мунька   (06.05.04 11:13) [6]

в Access - не решается в ИБ решается.


 
Курдль ©   (2004-05-06 11:16) [8]


> Соловьев ©

На ХП можно построить дерево с цепью, русалкой и ученым котом впридачу! Автор просил запрос. Но я считаю, что ради "дерева" не следует мучать сервер. Ведь все, что он сможет вернуть - последовательность деревянно-отсортированных записей! Преобразовывать их в стволы, ветки и узлы придется все равно на клиенте.


 
Мунька   (2004-05-06 11:19) [9]

>последовательность деревянно-отсортированных записей! >Преобразовывать их в стволы, ветки и узлы придется все равно на >клиенте.
Не вижу проблем такого преобразования


 
Соловьев ©   (2004-05-06 11:21) [10]


> Курдль ©   (06.05.04 11:16) [8]

а оракл вернет что? не
> последовательность деревянно-отсортированных записей!
?


 
Курдль ©   (2004-05-06 11:22) [11]


> Мунька   (06.05.04 11:19) [9]
> Не вижу проблем такого преобразования

Так я более того - не вижу проблем разложения древовидно-заточенного набора данных в дерево вовсе на клиенте! Это рекурсия в 10 строк!


 
Курдль ©   (2004-05-06 11:24) [12]


> Соловьев ©   (06.05.04 11:21) [10]
> а оракл вернет что? не
> > последовательность деревянно-отсортированных записей!

Ее самую, а где противоречия? Только оракл вернет по запросу, а не из ХП. Но я повторяю - чаще всего удобнее "делать дерево" на клиенте.


 
gu_est   (2004-05-06 11:26) [13]

>Курдль ©   (06.05.04 11:16) [8]
Что значит не мучать сервер? А кого мучать? Клиента?
Загнать на клиента ВСЕ и там строить дерево? А на кой тогда сервер вообще нужен?


 
Соловьев ©   (2004-05-06 11:28) [14]


> Только оракл вернет по запросу, а не из ХП

Просто разработчики Оракла уже это реализовали. Вот тебе и запрос. Но не вижу сложности в ХП...
не будем спорить, автор и сам решит что ему нужно...
Противоречие здесь.

> Преобразовывать их в стволы, ветки и узлы придется все равно
> на клиенте.

Таким образом я понял что Оракл вернет уже типа готовой компоненты... Значит я не понял ответа.
Но имхо ХП самое оно.


 
Sergey_Masloff   (2004-05-06 11:28) [15]

Курдль ©   (06.05.04 11:24) [12]
В запросе надо отобрать все счета клиента а клиент это иерархическая структура - центральный офис, представительства и так далее. Куда ты в этой задаче засунешь свое дерево на клиенте?
Это только самый простой пример реально деревью могут использоваться на сервере и покруче.


 
Курдль ©   (2004-05-06 11:29) [16]


> gu_est   (06.05.04 11:26) [13]
> Загнать на клиента ВСЕ и там строить дерево? А на кой тогда
> сервер вообще нужен?

Именно загнать на клиента ВСЕ! Ведь от перестроения записей их количество не изменится! А сервер БД нужен вовсе не для того, чтобы заниматься бантиками клиентского интерфейса.


 
Курдль ©   (2004-05-06 11:34) [17]


> Соловьев ©   (06.05.04 11:28) [14]

> Таким образом я понял что Оракл вернет уже типа готовой
> компоненты... Значит я не понял ответа.
> Но имхо ХП самое оно.

Нифига похожего оно не вернет! Только root-node-subnode...node-subnode-subsubnode... и т.д. Еще поле LEVEL.
Компонент визуальный наполнять все равно придется со стороны клиента - иначе никак!


 
Соловьев ©   (2004-05-06 11:34) [18]


> Ведь от перестроения записей их количество не изменится!
>

это если один клиент :)
А если много? У меня ветка строится когда пользователь решил ее рскрыть. И сразу выполняется запрос к БД. А в твоем варианте данные не актуальны.


 
Johnmen ©   (2004-05-06 11:36) [19]

>Именно загнать на клиента ВСЕ!

Да ? А если их много ? А нас много не интересует ?

>Ведь от перестроения записей их количество не изменится!

А где здесь "перестроение" ?


 
Курдль ©   (2004-05-06 11:37) [20]


> У меня ветка строится когда пользователь решил ее рскрыть.

Это разумно. Не спорю. Но я, чаще всего, беру TdxDBTreeList, подставляю ему набор данных и не парюсь :)


 
gu_est   (2004-05-06 11:43) [21]

Автор вообще не заострял внимание на визуализации дерева как такового (может полученный в результате запроса набор данных он собарается использовать для дальнейших вычислений, а не для визуализации в виде дерева).
Посему ХП (ИМХО) это то, что "доктор прописал"


 
Мунька   (2004-05-06 11:46) [22]

Ладно, ловите. Суть такая. Таблица, как я понимаю, как у нашего вопрошающего. Сначала я извлекаю данные все, а уж потом строю дерево, результат, то бишь дерево, скидываю в StringList

//---------------------------------------------------------------
//Извлечение всех записей и скидывание их в StringList при помощи рекурсивной функции RecursDepartment, для идентификаторов используется отдельный TStringList * DepListId
bool TDM::SelectAllDepartment(WideString ConnectionADO, TStringList * DepList, TStringList * DepListId)
{
int RecNo;

if(ADOQDepart->Active)
 ADOQDepart->Close();
  ADOConnection1->Connected  = false;
  ADOConnection1->ConnectionString = ConnectionADO;
  ADOConnection1->Connected  = true;
  ADOQDepart->Connection = ADOConnection1;

ADOQDepart->SQL->Clear();
ADOQDepart->SQL->Add("SELECT * FROM  tdivision ORDER BY id_parent, id_division");
try{
  ADOQDepart->Open();
}
catch(...)
{
 return false;
}
ADOQDepart->First();
DepList->Clear();

if(DepListId!=NULL)
DepListId->Clear();
while(!ADOQDepart->Eof&&(ADOQDepart->FieldByName("id_parent")->AsInteger==-1 ) )
{
  DepList->Add(ADOQDepart->FieldByName("name_division")->AsString);
    if(DepListId!=NULL)
      DepListId->Add(IntToStr(ADOQDepart->FieldByName("id_division")->AsInteger));

  RecNo =ADOQDepart->RecNo;
  RecursDepartment(DepList, ADOQDepart->FieldByName("id_division")->AsInteger, DepListId);
  ADOQDepart->RecNo=RecNo;
  ADOQDepart->Next();
}

return true;
}
//сама рекурсивная функция
void TDM::RecursDepartment(TStringList * DepList, int id_parent, TStringList * DepListId)
{
int RecNo;

 while(!ADOQDepart->Eof)
 {
  if(ADOQDepart->FieldByName("id_parent")->AsInteger==id_parent)
   {
    DepList->Add(ADOQDepart->FieldByName("name_division")->AsString);
    if(DepListId!=NULL)
      DepListId->Add(IntToStr(ADOQDepart->FieldByName("id_division")->AsInteger));
    RecNo = ADOQDepart->RecNo;
    RecursDepartment(DepList, ADOQDepart->FieldByName("id_division")->AsInteger, DepListId);
    ADOQDepart->RecNo=RecNo;

   }
   ADOQDepart->Next();
 }

}


 
Мунька   (2004-05-06 11:47) [23]

// и кусок кода, для вызова всего этого хозяйства, одна функция выводит в грид SetStringListToGrig, вторая - в дерево
DM->SelectAllDepartmentToTree
...........................................
DeparmentList = new TStringList();
DeparmentListId = new TStringList();
DM->SelectAllDepartment(ConnectionADO, DeparmentList, DeparmentListId);
  ClearGrid(SGDivision, MIN_ROWCOUNT_DEPARTMENT);
 SetStringListToGrig(SGDivision, DeparmentList, MIN_ROWCOUNT_DEPARTMENT, 0);
 SGDivisionSelectCell(Sender,  0, 1,CanSelect);
 DM->SelectAllDepartmentToTree(ConnectionADO, TreeViewDep);
.......... дальше по коду...........................
//----------------------SetStringListToGrig вывод извлеченного дерева в грид------
void SetStringListToGrig(TStringGrid *sg, TStringList *sl, int min_rowcount, int col_num)
{
int i;
for(i=0; i< sl->Count; i++)
{
  if(i==(sg->RowCount-sg->FixedRows ))
      sg->RowCount +=min_rowcount;
  sg->Cells[col_num][i+sg->FixedRows] = sl->Strings[i];

}

}


 
Мунька   (2004-05-06 11:48) [24]

//Вывод в дерево
bool TDM::SelectAllDepartmentToTree(WideString ConnectionADO, TTreeView *TreeViewDep)
{
int RecNo;

if(ADOQDepart->Active)
 ADOQDepart->Close();

 ADOQDepart->ConnectionString = ConnectionADO;
ADOQDepart->SQL->Clear();
ADOQDepart->SQL->Add("SELECT * FROM  tdivision ORDER BY id_parent, id_division");
try{
  ADOQDepart->Open();
}
catch(...)
{
 return false;
}
ADOQDepart->First();
TreeViewDep->Items->Clear();
while(!ADOQDepart->Eof&&(ADOQDepart->FieldByName("id_parent")->AsInteger==-1 ) )
{
 // DepList->Add(ADOQDepart->FieldByName("name_division")->AsString);
  TreeViewDep->Items->Add(NULL, ADOQDepart->FieldByName("name_division")->AsString);

  RecNo =ADOQDepart->RecNo;
 // RecursDepartmentList(DepList, ADOQDepart->FieldByName("id_division")->AsInteger, DepListId);
  RecursDepartmentList(TreeViewDep, ADOQDepart->FieldByName("id_division")->AsInteger, TreeViewDep->Items->Item[TreeViewDep->Items->Count-1]);
  ADOQDepart->RecNo=RecNo;
  ADOQDepart->Next();
}
// ADOQDepart->

return true;
}
//рекурсия построения дерева
void TDM::RecursDepartmentList(TTreeView *TreeViewDep, int id_parent, TTreeNode *NodeParent)
{
int RecNo;

 while(!ADOQDepart->Eof)
 {
  if(ADOQDepart->FieldByName("id_parent")->AsInteger==id_parent)
   {
    TreeViewDep->Items->AddChild(NodeParent, ADOQDepart->FieldByName("name_division")->AsString);
    RecNo = ADOQDepart->RecNo;
    RecursDepartmentList(TreeViewDep, ADOQDepart->FieldByName("id_division")->AsInteger, TreeViewDep->Items->Item[TreeViewDep->Items->Count-1]);
    ADOQDepart->RecNo=RecNo;

   }
   ADOQDepart->Next();
 }

}


 
Мунька   (2004-05-06 11:48) [25]

//И напоследок, есть предок, извлечь всех его потомков
bool TDM::SelectLastLevel(WideString ConnectionADO, int id_parent)
{
TStringList *Id= new TStringList(), *list_parent = new TStringList()  ;
int  i;    // * list_id = new [1], size_list_id = 1,
AnsiString InString;
 if(ADOQLastLevel->Active)
 ADOQLastLevel->Close();

 ADOQLastLevel->ConnectionString = ConnectionADO;
 list_parent->Add(IntToStr(id_parent));
 do{
     ADOQLastLevel->SQL->Clear();
    ADOQLastLevel->SQL->Add("SELECT id_division, id_parent FROM  tdivision WHERE id_parent IN(");
          InString = "";
    for(i=0; i<list_parent->Count; i++)
    {
     if ( ((i+1)%100)==0)
     {
       ADOQLastLevel->SQL->Add(InString);
       InString = "";
     }
     InString += list_parent->Strings[i];
     if(i<(list_parent->Count-1) )
      InString +=", ";
     else InString +=")";
    }
     ADOQLastLevel->SQL->Add(InString);
    ADOQLastLevel->SQL->Add("ORDER BY id_parent, id_division");
     try{
        if(!ADOQLastLevel->Prepared)
         ADOQLastLevel->Prepared = true;

        ADOQLastLevel->Open();
        }
     catch(...)
    {
        delete Id;
        delete list_parent;
       return false;
    }

      for(i=0; i<list_parent->Count; i++)
      {
        ADOQLastLevel->Filtered = false;
        ADOQLastLevel->Filter = "id_parent = "+ list_parent->Strings[i];
        try{
        ADOQLastLevel->Filtered = true;
        }
        catch(...)
        {
         continue;
        }
           if(ADOQLastLevel->RecordCount==0)
         Id->Add(list_parent->Strings[i]);

      }//end for

          list_parent->Clear();
      ADOQLastLevel->Filtered = false;
      ADOQLastLevel->First();
      while(!ADOQLastLevel->Eof)
      {
       list_parent->Add(ADOQLastLevel->FieldByName("id_division")->AsString);
       ADOQLastLevel->Next();
      }

    }
 while(ADOQLastLevel->RecordCount>0);
   
   ADOQLastLevel->SQL->Clear();
   ADOQLastLevel->SQL->Add("delete from tdivision_tmp");
    try{
         if(!ADOQLastLevel->Prepared)
         ADOQLastLevel->Prepared = true;

        ADOQLastLevel->ExecSQL();

      }
  catch(...)
  {
    delete Id;
   delete list_parent;
   return false;
  }

        ADOQLastLevel->SQL->Clear();
    ADOQLastLevel->SQL->Add("INSERT INTO tdivision_tmp ");
    ADOQLastLevel->SQL->Add("SELECT * FROM  tdivision WHERE id_division IN(");
   
        InString = "";
    for(i=0; i<Id->Count; i++)
    {
     if ( ((i+1)%100)==0)
     {
       ADOQLastLevel->SQL->Add(InString);
       InString = "";
     }
     InString += Id->Strings[i];
     if(i<(Id->Count-1) )
      InString +=", ";
     else InString +=")";
    }
       ADOQLastLevel->SQL->Add(InString);

     try{
         if(!ADOQLastLevel->Prepared)
         ADOQLastLevel->Prepared = true;

        ADOQLastLevel->ExecSQL();

      }
  catch(...)
  {
   delete Id;
   delete list_parent;
   return false;
  }

   delete Id;
   delete list_parent;
   return true;
}



 
Соловьев ©   (2004-05-06 11:49) [26]


> DepListId->Add(IntToStr(ADOQDepart->FieldByName("id_division")->AsInteger));

слабенько :) А как насчет AddObject? ИМХО возможностей больше. И для ИБ есть уже готовые с исходниками. Брать на www.fibplus.com.ua в старье


 
Мунька   (2004-05-06 11:55) [27]

>>слабенько :) А как насчет AddObject?
Никак. Не помню из каких соображений, но вариант с добавлением объекта был отброшен. Наверное, из-за того, что объект должен быть наследником TObject, все-таки, а не просто целым числом.


 
Курдль ©   (2004-05-06 11:55) [28]


> Мунька

Это все об одном дереве????????!!!!!!!   8-()
Я же сказал 10 строк, а не 510!


 
Соловьев ©   (2004-05-06 11:59) [29]


> Это все об одном дереве????????!!!!!!!   8-()
> Я же сказал 10 строк, а не 510!

конечно когда за тебя все сделали

> Но я, чаще всего, беру TdxDBTreeList, подставляю ему набор
> данных и не парюсь :)



> Мунька   (06.05.04 11:55) [27]
> >>слабенько :) А как насчет AddObject?
> Никак. Не помню из каких соображений, но вариант с добавлением
> объекта был отброшен. Наверное, из-за того, что объект должен
> быть наследником TObject, все-таки, а не просто целым числом.

При использовании AddObject можно в узле хранить ссылку на структуру где хранить об узле кучи инфы, котора облегчает построение.


 
Мунька   (2004-05-06 11:59) [30]

>Это все об одном дереве????????!!!!!!!   8-()
>Я же сказал 10 строк, а не 510!
Там разные варианты - вывод в грид, в дерево, поиск потомков.. то есть это еще и визуальная обработка


 
Мунька   (2004-05-06 12:01) [31]

>При использовании AddObject можно в узле хранить ссылку на >структуру где хранить об узле кучи инфы, котора облегчает >построение.
Можно, но в данной программе хрен редьки не слаще


 
Курдль ©   (2004-05-06 12:03) [32]


> Мунька   (06.05.04 11:48) [24]

ЗАЧЕМ ВЫ ЭТО ВЫЛОЖИЛИ???
Неужели чтобы "передать опыт"? То, что Вы понаписали внутри ХП - чудовищно! Какие-то временные таблицы, бесчисленные селекты...
Что Вы хотели показать?


 
Соловьев ©   (2004-05-06 12:06) [33]


>  То, что Вы понаписали внутри ХП - чудовищно!

это как раз клиент :)


 
Курдль ©   (2004-05-06 12:08) [34]

Вот клиент:

//------------------------------------------------------------------------------
procedure TfrmAccounts.SortAccList(aList: TList);
var y, iy: Integer; py: ptrAcc;
 procedure BuildLink(var ptr: ptrAcc; var Index: Integer);
 var x: Integer; px: ptrAcc;
 begin
  inc(Index);
  for x:=0 to aList.Count-1 do
   begin
    px:=aList.Items[x];
    if (px.pr = ptr.id) and (px.index = 0) then
     begin
      px.index:=Index;
      px.level:=ptr.level+1;
      BuildLink(px, Index);
      ptr.dt0:=ptr.dt0+px.dt0;
      ptr.kt0:=ptr.kt0+px.kt0;
     end;
   end;
 end;
begin
 if aList = nil then Exit;
 iy:=1;
 for y:=0 to aList.Count-1 do
  begin
   py:=aList.Items[y];
   if py.pr = 0 then
    begin
     py.index:=iy;
     BuildLink(py,iy);
    end;
  end;
 aList.Sort(SortCompareIndex);
end;
//------------------------------------------------------------------------------



 
Соловьев ©   (2004-05-06 12:08) [35]


> Можно, но в данной программе хрен редьки не слаще

ну-ну... советую взглянуть на исходники готовых DBTreeView


 
Johnmen ©   (2004-05-06 12:09) [36]

>Курдль ©   (06.05.04 12:03) [32]
>Что Вы хотели показать?

А то ты не понял ? :)
Показать, что CB круче D, и эту крутизну успешно штурмовал тов. Мунька
Кстати, что-то текста маловато он привел... Требую продолжения банкета !


 
Соловьев ©   (2004-05-06 12:11) [37]


> aList.Sort(SortCompareIndex);

странно...
aList.Sort(@SortCompareIndex);?
и вообще не понятно к чему твой код :)


 
}|{yk ©   (2004-05-06 12:14) [38]

http://delphimaster.net/view/3-1083829796/


 
Мунька   (2004-05-06 12:18) [39]

>Неужели чтобы "передать опыт"? То, что Вы понаписали внутри ХП -> чудовищно! Какие-то временные таблицы, бесчисленные селекты...
>Что Вы хотели показать?
Всего-навсего ответила на вопрос, где при построении дерева не использовалась НИКАКАЯ специфика СУБД, все в рамках Ansi - стандарта. Если за вас УЖЕ извлечены все потомки - это хорошо, здесь показано все с 0 (почти, как format c:).

Не считаю CB круче Делфи, просто пишу на нем, мне удобнее.
И еще не штурмовал, а штурмовалА


 
Курдль ©   (2004-05-06 12:18) [40]


> aList.Sort(@SortCompareIndex);

Не обязательно - можно и без @.


> и вообще не понятно к чему твой код :)

Да "не вынесла душа поэта" :))) Привел код, который выстраивает данные в древовидную структуру и еще суммирует остатки по счетам "вверх по иерархии". Это не 10 строк, а аж 30...


 
Курдль ©   (2004-05-06 12:29) [41]


> Мунька   (06.05.04 12:18) [39]
> Всего-навсего ответила на вопрос, где при построении дерева
> не использовалась НИКАКАЯ специфика СУБД, все в рамках Ansi
> - стандарта. Если за вас УЖЕ извлечены все потомки - это
> хорошо, здесь показано все с 0 (почти, как format c:).

Про "никакую специфику". А если Ваш юзер не имеет привелегий на создание временных таблиц?
И как Вы сами-то оцениваете "select в цикле" с клиента? Это нормально?


 
Johnmen ©   (2004-05-06 12:37) [42]

>Мунька
>Всего-навсего ответила на вопрос, где при построении дерева не использовалась НИКАКАЯ специфика СУБД,

Неужели ? А что по поводу временной таблицы ? Откуда она ? И что с ней ?
И насколько это эффективно ?

>все в рамках Ansi - стандарта.

В смысле ?

>И еще не штурмовал, а штурмовалА

Виноват. Сразу не сообразил...:)


 
Мунька   (2004-05-06 12:46) [43]

>А если Ваш юзер не имеет привелегий на создание временных таблиц?
Таблица создается в шаблоне базе данных не юзером

>И как Вы сами-то оцениваете "select в цикле" с клиента? Это нормально?
Это нормально, поскольку приведенный код не есть клиент-серверное приложение, а программа, функционирующая на одном компе, создание деревьев подразделей - не ее цель, а так, утилита для удобства юзера, не более того


 
Мунька   (2004-05-06 12:47) [44]

Вернее сама программа клиент... но в совершенно другом смысле, к БД не имеющем отношение


 
Курдль ©   (2004-05-06 12:56) [45]


> Это нормально, поскольку приведенный код не есть клиент-серверное
> приложение, а программа, функционирующая на одном компе,
> создание деревьев подразделей - не ее цель, а так, утилита
> для удобства юзера, не более того

Создание деревьев - это всегда не цель. Чаще всего цель - автоматизация какого-нибудь процесса.
А то, что Ваша программа не гоняет "select + Набор данных" и "insert + Набор данных" тысячи раз за единичный цикл построения дерева по сети, а лишь внутри отдельно взятого компа Вы считаете хорошим основанием?..


 
Мунька   (2004-05-06 13:02) [46]

> а лишь внутри отдельно взятого компа Вы считаете хорошим >основанием?..
Скорее не являющимся критичным - из поставленной задачи. Поскольку известно, что дерево подразделений не будет большим, соответсвенно не будет тысяч Select и Insert + требования к ресурсам компа (в силу других решаемых задач) достаточно высоки. Хотя, действительно, использование временной таблицы не есть хорошо в принципе,но в данном случае допустимо - учитывая временные рамки разработки и полное отсутсвие времени на оптимизацию


 
Соловьев ©   (2004-05-06 13:04) [47]


> Мунька   (06.05.04 12:47) [44]

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=488
тоже не привязано к серверу. Очень поучительная статья


 
}|{yk ©   (2004-05-06 13:04) [48]

Посмотри код по ссылке. После выполнения 1 запроса далее идет один цикл по полученному результату и строится дерево. Время выполнения и построения минимально


 
Курдль ©   (2004-05-06 13:11) [49]


> Скорее не являющимся критичным - из поставленной задачи.
> Поскольку известно, что дерево подразделений не будет большим,
> соответсвенно не будет тысяч Select и Insert + требования
> к ресурсам компа (в силу других решаемых задач) достаточно
> высоки.

А Вы, девушка, не в Microsoft работаете с Вашим замахом на ресурсы? :)  Я же привел пример кода, который в тысячи раз эффективнее Вашего. Что может быть проще?
Разве что сканировать ChildLevel только при раскрытии узла, как писал Соловьев ©   (06.05.04 11:34) [18]
(И это наиболее экономичный способ, если не надо делать никаких "восходящих расчетов", как в моем случае).


 
Мунька   (2004-05-06 13:32) [50]

Смею заметить, что Вы не привели кусок кода формирования вашего листа, содержащего дерево


 
Курдль ©   (2004-05-06 13:35) [51]


> Мунька   (06.05.04 13:32) [50]
> Смею заметить, что Вы не привели кусок кода формирования
> вашего листа, содержащего дерево

Оно немного больше того, которое строите Вы (по функциональности а не размеру кода) - включает в себя разнообразные признаки и графические элементы, но если Вы подтвердите свое желание - след. постом выложу.


 
}|{yk ©   (2004-05-06 13:42) [52]

Кстати функция формирования дерева

procedure TFormCUST2TREE.GenerateTree(ID: Integer);
var
column: Integer;
Node: tdxTreeListNode;
find: Boolean;
pid: string;
begin
DataModuleMain.APP_CUST2_TREE.Active:=False;
     DataModuleMain.APP_CUST2_TREE.ParamByName("VSET_ID").AsInteger:=ID;
DataModuleMain.APP_CUST2_TREE.Active:=True;
DataModuleMain.APP_CUST2_TREE.First;
column:=dxTreeListCUST2TREEMEM_ID.Index;
while not DataModuleMain.APP_CUST2_TREE.Eof do
 begin
  pid:=DataModuleMain.APP_CUST2_TREEMEM_PID.AsString;
  dxTreeListCUST2TREE.StartSearch(column, pid);
  find:=dxTreeListCUST2TREE.FocusedNode<>nil;
  if (find) then
  node := dxTreeListCUST2TREE.FocusedNode.AddChild
   else
     node := dxTreeListCUST2TREE.Add;
  SetNodeValues(Node,DataModuleMain.APP_CUST2_TREEMEM_ID.AsString,DataModuleMain.APP_CUST2_TREEMEM_NAME.AsString,pid);
  DataModuleMain.APP_CUST2_TREE.Next;
 end;
 dxTreeListCUST2TREE.GotoFirst;
end;


 
Соловьев ©   (2004-05-06 13:44) [53]


> }|{yk ©   (06.05.04 13:42) [52]
> Кстати функция формирования дерева

procedure TForm1.FormActivate(Sender: TObject);
begin
 DBVirtualStringTree1.LoadTree;
end;
И все :)))


 
Курдль ©   (2004-05-06 13:46) [54]


> }|{yk ©   (06.05.04 13:42) [52]
> Кстати функция формирования дерева

Забавная методика построения дерева методами древовидного компонента :)


 
Курдль ©   (2004-05-06 14:03) [55]

Ладно, чтобы не быть голословным к своим разглагольствованиям о пользе построения дерева на клиенте приложу код, который был создан несколько лет назад и вместе с [34] успешно реализовывал отображение набора данных, единожды полученного от бд и переписанного в List:

//------------------------------------------------------------------------------
procedure TfrmAccounts.ListToTree(aList: TList);
var i, act, lev: Integer; P: ptrAcc;
   dxnArr: array [0..63] of TdxTreeListNode;
begin
 dxt1.ClearNodes;
 dxnArr[0]:=dxt1.AddFirst; if dxnArr[0]<>nil then dxnArr[0].MakeVisible;
 dxnArr[0].Data:=Ptr(0);
 dxnArr[0].ImageIndex:=0;
 dxnArr[0].SelectedIndex:=1;
 dxnArr[0].Strings[0]:="&#208;&#229;&#229;&#241;&#242;&#240; &#241;&#247;&#229;&#242;&#238;&#226;";
 dxnArr[0].Strings[1]:=dmSB.SelfUlName;

 if aList = nil then Exit;
 dxt1.Visible:=False;
 for i:=0 to aList.Count-1 do
  begin
   P:=aList.Items[i];
   lev:=P.level;
   dxnArr[lev]:=dxnArr[lev-1].AddChild; if dxnArr[lev]<>nil then dxnArr[lev].MakeVisible;
   dxnArr[lev].Data:=Ptr(P.id);
   dxnArr[lev].Strings[0]:=P.num;
   dxnArr[lev].Strings[1]:=P.name;
   case P.act of
   -1: begin
        dxnArr[lev].ImageIndex:=2;
        dxnArr[lev].SelectedIndex:=3;
        dxnArr[lev].Strings[2]:="&#192;&#234;&#242;&#232;&#226;";
       end;
    0: begin
        dxnArr[lev].ImageIndex:=4;
        dxnArr[lev].SelectedIndex:=5;
        dxnArr[lev].Strings[2]:="&#192;&#234;&#242;&#232;&#226;/&#239;&#224;&#241;&#241;&#232;&#226;";
       end;
    1: begin
        dxnArr[lev].ImageIndex:=6;
        dxnArr[lev].SelectedIndex:=7;
        dxnArr[lev].Strings[2]:="&#207;&#224;&#241;&#241;&#232;&#226;";
       end;
   end;
   case P.col of
    1: begin
        dxnArr[lev].StateIndex:=8;
        dxnArr[lev].Strings[3]:="&#193;&#224;&#235;&#224;&#237;&#241;&#238;&#226;&#251;&#233;";
       end;
    2: begin
        dxnArr[lev].StateIndex:=9;
        dxnArr[lev].Strings[3]:="&#199;&#224;&#225;&#224;&#235;&#224;&#237;&#241;&#238;&#226;&#251;&#233;";
       end;
    3: begin
        dxnArr[lev].StateIndex:=10;
        dxnArr[lev].Strings[3]:="&#194;&#241;&#239;&#238;&#236;&#238;&#227;&#224;&#242;&#229;&#235;&#252;&#237;&#251;&#233;";
       end;
   else begin
         dxnArr[lev].StateIndex:=10;
         dxnArr[lev].Strings[3]:="&#205;&#229; &#238;&#239;&#240;&#229;&#228;&#229;&#235;&#229;&#237;";
        end;
   end;
   if P.dt0<>0 then dxnArr[lev].Values[4]:=P.dt0;
   if P.kt0<>0 then dxnArr[lev].Values[5]:=P.kt0;
   if lev>1 then dxnArr[lev-1].Collapse(false);
  end;
 dxt1.FullCollapse;
 dxnArr[0].Expand(false);
 dxt1.Visible:=True;
end;
//------------------------------------------------------------------------------



 
}|{yk ©   (2004-05-06 14:12) [56]

>Забавная методика построения дерева методами древовидного компонента :)
Чем забавная? Нет у этого компонента функции загрузки дерева


 
Курдль ©   (2004-05-06 14:17) [57]


> }|{yk ©   (06.05.04 14:12) [56]
> >Забавная методика построения дерева методами древовидного
> компонента :)
> Чем забавная? Нет у этого компонента функции загрузки дерева

Тем и забавная, что применяются методы самого же компонента типа
StartSearch. Я не сказал, что плохая. А о том, что нет метода загрузки мне рассказывать и не надо - см. [55]


 
goozman   (2004-05-14 09:00) [58]

Знаете, я почитал ....-Все это полнейший бред!
Вот я решил свою проблему процедурой рекурсии

ВХОД (ROTT)
ИСХОД (ID)
ПЕР(CUR_NODE)

begin
 for select d.id
     from department d
     where d.parent_id = :root
     into :id do
     begin
       suspend;
       cur_node = id;
       for select id from temp(:CUR_NODE)
           into :id do suspend;
     end
end


 
gu_est   (2004-05-14 09:28) [59]

о чем я и говорил [21], а все уперлись в визуализацию...


 
Соловьев ©   (2004-05-14 09:29) [60]


> 59] gu_est

см. первый пост. Там все это уже давно было.


 
Digitman ©   (2004-05-14 13:16) [61]


> goozman   (14.05.04 09:00) [58]


все верно) ... для концептуального решения задачи достаточно реализации вот такой вот рекурс.ХП

клиент, обращаясь к такой ХП, получает курсор НД и волен двигать его как угодно - хоть для позиционирования/выборки одной нужной ему записи, хоть для позиц-я/выборки всего результирующего НД .. а уж как клиент будет всю эту бодягу визуализировать - это не проблема сервера)


 
}|{yk ©   (2004-05-14 13:43) [62]

А в [38] и [48] я что предлагал, не рекурсию?



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

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

Наверх




Память: 0.67 MB
Время: 0.029 c
3-1084562937
Ertong
2004-05-14 23:28
2004.06.06
select max from someDB


1-1085382966
RoadStar
2004-05-24 11:16
2004.06.06
Рисование в TTreeView


3-1084621672
havez
2004-05-15 15:47
2004.06.06
BDE


14-1085052644
Igor_thief
2004-05-20 15:30
2004.06.06
Путин подписал антихакерский указ


14-1084813569
Nomolos
2004-05-17 21:06
2004.06.06
Кто-нибудь имел опыт профессиональной работы с AudioCD