Форум: "Базы";
Текущий архив: 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...
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];
Память: 0.64 MB
Время: 0.049 c