Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS Access > иерархия данных


Автор: Sawell 4.1.2010, 16:49
Есть таблица с полями  Name, id, ParentID. Для постарения дерева через TreeView. Встал вопрос как можно просмотреть всех детей от выбранного родителя. При щелчке на нод в дереве получаю id данного нода.  Проблема вся в том что групп и подгрупп может быть множество. 

К примеру. 
 A
_|_
B  C
      _|_
     D   E  и т. Д.  



Name    ID     ParentID
A            1            0
B            2           1
C            3           1
D            4           3
E            5           3

Так вот при получении id Группы А нужно получить id всех входящих в нее подгрупп т.е. B C D E. Причем эти данные нужны в запросе, для сортировки по ним товаров.

Буду рад любому совету.   smile 

Автор: bopoha 4.1.2010, 18:11
Такие id-и одним запросом не достанешь, т.к. нет рекусрсии. Только ручками сформировать - либо во временную таблиц, либо в масив, либо сгенерить множество запросов и объединить их в union.

Автор: Sawell 4.1.2010, 18:34
 bopoha, Дык я понимаю что одним запросом не обойдешся. Через запросы получилось провалиться максимум до 3го уровня. Бли запарился я совсем на этом месте. А если делать функцию, то там цикл нужен( если не ошибаюсь) а вот хотелось бы без него. 

Автор: bopoha 4.1.2010, 18:40
Ох, и чем плох цикл? 
Не хотите цикл - убирайте древовидную иерархию.
За дерево нужно платить не только циклом но N-ым количеством запросов, где N "глубина" дерева.

Автор: Akina 4.1.2010, 18:45
Существует достаточно много разных схем хранения и получения деревьев. Каждый оптимизирован для своей ситуации.
Для выбора подходящей схемы хранения нужно гораздо больше данных.

Я в принципе не понял вот этого:
Цитата(Sawell @  4.1.2010,  17:49 Найти цитируемый пост)
при получении id Группы А нужно получить id всех входящих в нее подгрупп 

Оно тебе, я извиняюсь, нахрена? запихай данные в TreeView, и пусть он этими проблемами занимается. Поверь, у него получится лучше, чем у тебя.

Автор: Sawell 4.1.2010, 18:48
bopoha, делать N запросов не вариант! Я же не могу пердугадать сколько подгрупп сделает оператор.

Добавлено через 4 минуты и 44 секунды
Akina,  Вот ситуация у меня есть группа (глобальная) ну к примеру "Транспорт" в ней есть подгруппа "легковой", "грузовой" и т.д. а в подгруппе "грузавой" есть еще подгруппа "Тяжелый" а в этой подруппе еще..... Так вот  к примеру при выборе в дереве группы "транспорт" в форме отображались данные входяшие во все ниже лежашие группы.

Автор: bopoha 4.1.2010, 18:57
Цитата(Sawell @  4.1.2010,  18:48 Найти цитируемый пост)
bopoha, делать N запросов не вариант! Я же не могу пердугадать сколько подгрупп сделает оператор.

Динамически можно посчитать!

Добавлено через 1 минуту и 36 секунд
Помойму проблема надумана. Это простая задача. Берется и делается. Не устраивает производительность - оптимизируется алгоритм и/или способ хранения данных.

Автор: Akina 4.1.2010, 19:56
Цитата(Sawell @  4.1.2010,  19:48 Найти цитируемый пост)
Вот ситуация у меня есть группа (глобальная) ну к примеру "Транспорт" в ней есть подгруппа "легковой", "грузовой" и т.д. а в подгруппе "грузавой" есть еще подгруппа "Тяжелый" а в этой подруппе еще..... Так вот  к примеру при выборе в дереве группы "транспорт" в форме отображались данные входяшие во все ниже лежашие группы. 

Повторяю ещё раз. Для ещё не отошедших от празднования.
Загрузи данные в TreeView в соответствии с иерархией. Всё. Дальше это его забота - развернуть по клику выбранную группу и показать её подгруппы/элементы.

Автор: Sawell 4.1.2010, 23:38
Akina, данные в подчиненной форме. Т.е. В группе содержатся наименования. Дерево уже есть и работает! в дереве отобр. группы по которым я и хожу. но вот если я выбераю основную группу (в которой еще есть n-ое кол-во подгруп) то в результате в подчин. форме должны отоб. данные из всех групп входяших в основную! Короче просматривать всех детей и закидывать их во врем. табл. это получилось, (код потом) но временные табл. это не есть хорошо. Хотелось бы сразу в запрос...

Автор: Akina 4.1.2010, 23:51
Ага... у тебя там ещё и подчинённая форма, оказывается... знаешь что, рассказывай-ка ты сразу всё, а не по кусочкам. А то телепаты, как обычно, в отпуске.

Добавлено через 55 секунд
А ещё лучше - почитай http://forum.vingrad.ru/forum/topic-260944.html. И поступай соответственно.

Автор: bopoha 5.1.2010, 11:38
Цитата(Sawell @  4.1.2010,  23:38 Найти цитируемый пост)
но временные табл. это не есть хорошо. 

Глупости. Кто тебе сказал? Что бы не "засирать" основную бд стоит временные таблицы хранить в отдельном файле и пересоздавать ее при запуске. У меня такая система отлично работает.

Автор: Sawell 5.1.2010, 14:40
Ну в общем нашел такие пути. В первом случае созд-ю запрос где делаю отборку групп и уже его связываю с запросом, который делает отбор товара. Во втором принцип получения списка тот же только здесь я получаю данные в поле в форме в виде id Or id Or id Or id …..(11 Or 12  Or 13 Or 14….) НО со вторым вариантом проблема запрос на выборку не хочет принимать это поле (слишком сложное или неправильное выражение). Оно и понятно я ведь в SQL виде получаю что-то в виде WHERE [id]= Forms![NameForms]![idForm]. Этот  вариант работает если в конструкторе в условие отбора прям вставить   11 Or 12  Or 13 Or 14… тогда он понимает что я хочу WHERE [id]=11 Or [id]=12 … Второй вариант был бы конечно лучше так как его можно испл. не только  для формирования отчетов но и для отобр-я данных в подчиненной форме задавая этим полем условие отбора.

Код

Public Function GrWhere(lId As Long, sTblName As String, sCrit As String) '(1й вариант 1я часть)
'Возвращает строку WHERE без ключевого слова в структуре с двумя полями
Dim txt As String
Dim rs As Recordset
    If sCrit <> "" Then
        sCrit = sCrit + " OR id = " & lId
    Else
        sCrit = sCrit + " id = " & lId
    End If
txt = "SELECT * FROM " & sTblName & " WHERE ParentID = " & lId
Set rs = CurrentDb.OpenRecordset(txt)
Do Until rs.EOF
    Call GrWhere(rs![id], sTblName, sCrit)
rs.MoveNext
Loop
End Function

Код

Public Function allChildintabl(tvwObj As Object, lId As Long, sTblName As String) As Boolean  ' переносит всех детей и родителя в таблицу/запрос (1й вар. 2я часть)
Dim rs As Recordset
Dim sCrit As String

Call GrWhere(lId, sTblName, sCrit)
    Set rs = CurrentDb.OpenRecordset("Select * FROM " & sTblName & " WHERE " & sCrit)
    If Not rs.EOF Then
        rs.MoveLast
        rs.MoveFirst
    End If
    'CurrentDb.Execute "INSERT INTO tempGT ([Название группы], [id], [ParentID]) Select * FROM " & sTblName & " WHERE " & sCrit ' данные в табл
CurrentDb.QueryDefs.Delete "~Temp"
CurrentDb.CreateQueryDef "~Temp", "Select * FROM " & sTblName & " WHERE " & sCrit   'Создание запроса и доб. в него данных
DoCmd.OpenQuery "~Temp"
End Function

-----------------------------------------------Вар 2 -----------------------------------------------
Код

Public Function GrWhere2(lId As Long, sTblName As String, sCrit As String)
'Возвращает строку WHERE без ключевого слова в структуре с двумя полями
Dim txt As String
Dim rs As Recordset
    If sCrit <> "" Then
        sCrit = sCrit + " " + "Or" + " " & lId
    Else
        sCrit = sCrit & lId
    End If
txt = "SELECT * FROM " & sTblName & " WHERE ParentID = " & lId
Set rs = CurrentDb.OpenRecordset(txt)
Do Until rs.EOF
    Call GrWhere2(rs![id], sTblName, sCrit)
rs.MoveNext
Loop
End Function
Public Function InErarx(tvwObj As Object, lId As Long, sTblName As String) As Boolean  ' переносит всех детей и родителя в таблицу

Dim sCrit As String
Call GrWhere2(lId, sTblName, sCrit)
    
Forms!Сортамент![as] = sCrit
'InErarx = sCrit

End Function

Автор: FINANSIST 15.1.2010, 10:39
Цитата(Sawell @  4.1.2010,  16:49 Найти цитируемый пост)
Ну в общем нашел такие пути. В первом случае созд-ю запрос где делаю отборку групп и уже его связываю с запросом, который делает отбор товара. Во втором принцип получения списка тот же только здесь я получаю данные в поле в форме в виде id Or id Or id Or id …..(11 Or 12  Or 13 Or 14….) НО со вторым вариантом проблема запрос на выборку не хочет принимать это поле (слишком сложное или неправильное выражение). Оно и понятно я ведь в SQL виде получаю что-то в виде WHERE [id]= Forms![NameForms]![idForm]. Этот  вариант работает если в конструкторе в условие отбора прям вставить   11 Or 12  Or 13 Or 14… тогда он понимает что я хочу WHERE [id]=11 Or [id]=12 … Второй вариант был бы конечно лучше так как его можно испл. не только  для формирования отчетов но и для отобр-я данных в подчиненной форме задавая этим полем условие отбора.
Public Function GrWhere(lId As Long, sTblName As String, sCrit As String) '(1й вариант 1я часть)
........................................................................................................................................................

smile))
А что, Nested Sets нынче не в моде?

Автор: Sawell 15.1.2010, 14:50
Цитата

А что, Nested Sets нынче не в моде?



FINANSIST, Мммм. А с чем это едят??? smile 

Автор: Akina 15.1.2010, 14:54
Цитата(Sawell @  15.1.2010,  15:50 Найти цитируемый пост)
с чем это едят???   

C Гуглом  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)