Войти

Показать полную графическую версию : Вывод родствеников


student_po
23-04-2013, 09:01
Доброго времени суток. Есть база в access с именем члена семьи и данными о родителях.
Из этой базы как нужно вывести всех предков данного человека. Заранее спасибо всем.

lxa85
23-04-2013, 10:26
student_po, это надо сделать средствами Access? Или средствами Delphi? Потому что средствами Access это проблематично. Средствами Delphi -- это задача на графы.

Iska
23-04-2013, 11:41
Потому что средствами Access это проблематично. »
Почему? Обычная рекурсия (концепт, без необходимых проверок):
Option Compare Database
Option Explicit

Sub Sample(strFIO As String)
Dim objRS As Recordset
Dim lngLevel As Long


lngLevel = 0

Set objRS = CurrentDb.OpenRecordset("SELECT * FROM Genealogy WHERE [ФИО] = '" & strFIO & "'")

GetParents objRS.Fields.Item("ID").Value, lngLevel
End Sub

Sub GetParents(lngID As Long, ByVal lngLevel)
With CurrentDb.OpenRecordset("SELECT [ФИО], [Отец], [Мать] FROM Genealogy WHERE [ID] = " & lngID & "")
With .Fields
Debug.Print String(lngLevel, vbTab) & .Item("ФИО").Value

lngLevel = lngLevel + 1

If Not IsNull(.Item("Отец").Value) Then
GetParents .Item("Отец").Value, lngLevel
End If

If Not IsNull(.Item("Мать").Value) Then
GetParents .Item("Мать").Value, lngLevel
End If
End With
End With
End Sub

Примерный результат работы по вызову «Sample("Я")»:
Я
Папа
Дед (отец отца)
Бабка (мать отца)
Мама
Дед (отец матери)
Бабка (мать матери)

student_po
23-04-2013, 12:18
Средствами Delphi

Iska
23-04-2013, 13:10
student_po, так переведите с VBA на Delphi. Алгоритм один и тот же.

lxa85
23-04-2013, 14:41
Iska, я с Access ом не работал. Поэтому я затруднился дать ответ. Была мысль написания единого SQL запроса, и она потонула в сомнениях (AFAIK SQL не поддерживает рекурсию). Поэтому возникла мысль запросить всю таблицу в Delphi, сформировать массива и работать с ним как с матрицей, описывающий граф гинеалогического дерева.

Iska
23-04-2013, 15:11
lxa85, а мне сразу PROLOG вспомнился ;).

lxa85
23-04-2013, 17:21
Iska, :yes:

student_po
23-04-2013, 18:13
procedure TForm1.genealogy(iddb:integer);
var f,m:integer;
begin
Datam.ADOQuery3.Locate('id',iddb, []);
if Datam.ADOQuery3.FieldByName('Отец').AsInteger<>0 then
begin
f:=(datam.ADOQuery3.FieldByName('Отец').AsInteger);
Memo2.Lines.Add(inttostr(f));
Datam.ADOQuery3.Locate('id',f, []);
genealogy(Datam.ADOQuery3.FieldByName('id').AsInteger);
end;
if Datam.ADOQuery3.FieldByName('Мать').AsInteger<>0 then
begin
m:=(datam.ADOQuery3.FieldByName('Мать').AsInteger);
Memo2.Lines.Add(inttostr(m));
Datam.ADOQuery3.Locate('id',m, []);
genealogy(Datam.ADOQuery3.FieldByName('id').AsInteger);
end;
end;

До деда по отцу доходит и встали. Где я скриворукил.

Iska
23-04-2013, 18:46
student_po, обратите внимание на разницу — я сначала выбираю запись, делаю вывод «ФИО», затем проверяю в записи свойства «Отец»/«Мать» и, если они не пустые — рекурсивно вызываю процедуру. В Вашем коде логика иная: если у деда нет «Отца» — самого деда в «Memo2» Вы не увидите.




© OSzone.net 2001-2012