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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.68 MB
Время: 0.044 c
1-1085334358
Sanek_metaller
2004-05-23 21:45
2004.06.06
Лишние BMP и Курсоры...


4-1083680287
Sir Kik
2004-05-04 18:18
2004.06.06
Скопировать Desktop - окно


14-1085062009
Копир
2004-05-20 18:06
2004.06.06
Израиль мало-помалу забывает свою историю.


14-1084538079
TRX
2004-05-14 16:34
2004.06.06
rabota v turbo pascal


3-1084527737
}|{yk
2004-05-14 13:42
2004.06.06
Никто не знает как поще преобразовать timestamp в строку типа





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский