Проблема с построением дерева по структуре из mdb

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Проблема с построением дерева по структуре из mdb

Сообщение Алексей К. » 16.10.2006 (Пн) 9:05

имею структуру дерева в access:
(код,key,parent_key,text)
ключ вида "123key", т.е. цифра + "key".
Изначально структуру беру с винчестера и записываю ее в базу, тем самым при сортировке по полю "код" имею правильный порядок узлов и дерево строится без проблем. В клиенте есть фича по перемещению узлов, так вот при повторном запуске в процессе построения дерева порядок следования узлов становиться не правильным (например сначала идет запись дочернего узла, а за ней запись узла - родителя) и в момент создания дочернего узла его родительский узел еще не создан - соответственно ошибка "Элемент не найден (родитель)". Как правильно упорядочить набор записей в отношении потомок-родитель? Естественно одним запросом здесь не обойтись, может кто уже занимался упорядочиванем структуры дерева?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 16.10.2006 (Пн) 9:18

Добавь еще одно поле, Level. Сортируй по нему. Тогда описанной проблемы не будет.
Lasciate ogni speranza, voi ch'entrate.

Алексей К.
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 419
Зарегистрирован: 12.05.2004 (Ср) 9:41
Откуда: Ульяновск

Сообщение Алексей К. » 16.10.2006 (Пн) 9:21

Спасибо :), по пробую.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 16.10.2006 (Пн) 9:56

Рекомендую изменить структуру таблицы в соответствии с принципом вложенных множеств. Если требуется активная работа с ветками, то такая структура удобнее.
http://www.webscript.ru/stories/04/09/01/8197045
Лучший способ понять что-то самому — объяснить это другому.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 16.10.2006 (Пн) 10:05

Antonariy, в целом да.
Но для простых случаев удобнее использовать простые решения (типа поля level или fullpath).
Lasciate ogni speranza, voi ch'entrate.

Alexanbar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1727
Зарегистрирован: 13.04.2004 (Вт) 23:04
Откуда: Волгоградская обл.

Сообщение Alexanbar » 16.10.2006 (Пн) 10:14

Создать запрос с новым полем типа "полный путь" и отсортировать по нему

HandKot
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 283
Зарегистрирован: 28.06.2006 (Ср) 13:34
Откуда: Sergiev Posad

Сообщение HandKot » 16.10.2006 (Пн) 10:25

если данных не много, то можно применить и такой вариант

1 заход - заполняем дерево у узлов не указываем родителя
2 заход - проставляем парентов
I Have Nine Lives You Have One Only
THINK!

RayShade
Scarmarked
Scarmarked
Аватара пользователя
 
Сообщения: 5511
Зарегистрирован: 02.12.2002 (Пн) 17:11
Откуда: Russia, Saint-Petersburg

Сообщение RayShade » 17.10.2006 (Вт) 11:15

HandKot

Это прокатит, возможно только в VBNET. Стандартный treeview6, такого не умеет.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 17.10.2006 (Вт) 11:34

Сортировку в баню, разве что оставить в пределах узла.
Код: Выделить всё
Sub FillTree(rsValues As ADODB.Recordset, tv As TreeView)
    rsValues.Filter = "parent_key=null"
    'Здесь можно сделать например rsValues.Sort = "Text "
    While Not rsValues.EOF
        tv.Nodes.Add , , "i" & rsValues!код, rsValues!Text
        FillSubTree rsValues.Clone, tv, "i" & rsValues!код, rsValues!Key
        rsValues.MoveNext
    Wend
End Sub

Sub FillSubTree(rsValues As ADODB.Recordset, tv As TreeView, pTreeKey As String, PKval As Long)
    rsValues.Filter = "parent_key=" & PKval
    'Здесь можно сделать например rsValues.Sort = "Text "
    While Not rsValues.EOF
        tv.Nodes.Add pTreeKey, tvwChild, "i" & rsValues!код, rsValues!Text
        FillSubTree rsValues.Clone, tv, "i" & rsValues!код, rsValues!Key
        rsValues.MoveNext
    Wend
End Sub
На больших рекордсетах этот способ не будет поражать скоростью. Зато можно избавиться от поля key, а в parent_key хранить значения поля "код".
Лучший способ понять что-то самому — объяснить это другому.

HandKot
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 283
Зарегистрирован: 28.06.2006 (Ср) 13:34
Откуда: Sergiev Posad

Сообщение HandKot » 17.10.2006 (Вт) 14:42

RayShade писал(а):HandKot
Это прокатит, возможно только в VBNET. Стандартный treeview6, такого не умеет.


не только в НЕТ

Код: Выделить всё
Private Sub test()
    Dim nodX As Node
   
    'заполняем дерево
    Set nodX = trv.Nodes.Add(, , "q", "q")
    Set nodX = trv.Nodes.Add(, , "w", "w")
    Set nodX = trv.Nodes.Add(, , "e", "e")
    Set nodX = trv.Nodes.Add(, , "r", "r")
    Set nodX = trv.Nodes.Add(, , "t", "t")
    Set nodX = trv.Nodes.Add(, , "y", "y")
    Set nodX = trv.Nodes.Add(, , "u", "u")
   
    'проставляем парентов
    Set trv.Nodes("w").Parent = trv.Nodes("q")
    Set trv.Nodes("r").Parent = trv.Nodes("e")
    Set trv.Nodes("t").Parent = trv.Nodes("y")
   

End Sub
I Have Nine Lives You Have One Only
THINK!

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 17.10.2006 (Вт) 15:53

HandKot писал(а):1 заход - заполняем дерево у узлов не указываем родителя
2 заход - проставляем парентов
Вариант неплох, но уже на 10000 узлов со сложной и глубокой вложенностью время формирования дерева будет сильно больше однопроходного варианта.

Вариант Alexanbar я часто использую на стороне клиента - действительно, сортировать очень удобно. В базе этот вариант, к сожалению, практически неработоспособен по причине сильного ограничения уровня вложенности со стороны максимальной длины строкового поля в БД.

У себя в MSSQL я храню в таблице ParentId со ссылкой на первичный ключ родительского узла. Ну а отсортированное дерево получаю вызовом table-valued function, внутри которой используется цикл. Ничего лучше я не нашел, сколько ни искал. Так что, если аксесс знает, что такое UDF, хранимые в базе, то это будет, возможно, лучший вариант.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.10.2006 (Вт) 16:25

Увы, Access функций не позволяет.
Lasciate ogni speranza, voi ch'entrate.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.10.2006 (Вт) 16:28

Ennor писал(а):Вариант неплох, но уже на 10000 узлов со сложной и глубокой вложенностью время формирования дерева будет сильно больше однопроходного варианта.

Я думаю, что для десяти тысяч узлов уже имеет смысл изменить схему данных на то, что предложил Antonariy (Nested Sets) :)
Lasciate ogni speranza, voi ch'entrate.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 17.10.2006 (Вт) 16:51

alibek писал(а):Я думаю, что для десяти тысяч узлов уже имеет смысл
... сменить БД :)


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Mail.ru [бот] и гости: 101

    TopList