Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Cуммирование ветки иерархического дерева / 17 сообщений из 17, страница 1 из 1
02.09.2003, 15:24
    #32253795
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Собственно есть необходимость просуммировать некую ветку. Структура таблички стандартная:
ИдЗаписи/ИдВладельца/ПолеКотороеНадоСуммировать/ПрочийМусор

Вопрос: как это лучше реализовать?

Пока я сделал в виде рекурсивной функции. И возникла проблема - при прочих равных расчет одной ветки занимает в 10-15 раз больше времени (примерно 70 против 5 секунд), если в конце функции стоит связка

rst.close
set rst = nothing

Убирать - страшно, мало ли потом аукнется. Не убирать плохо - полторы минуты для того, чтобы пробежать по паре сотен записей...

Можно пользоваться dlookupom, не пробовал еще. Но ведь наверняка есть объезженные способы...

Спасибо.
...
Рейтинг: 0 / 0
02.09.2003, 15:34
    #32253808
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Круто... это что же, частый вызов
rst.Close
Set rst=Nothing
замедляют код в разы ??!!?? Есть над чем задуматься...
...
Рейтинг: 0 / 0
02.09.2003, 15:38
    #32253814
Shkurenko Alexander
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Нарисуй код полностью, если это не военная тайна ;-). Скорее всего уходит время на создание Recordset'a
...
Рейтинг: 0 / 0
02.09.2003, 15:46
    #32253831
Павел Воронцов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Совет - измените структуру хранения дерева. Вариантов - масса, они опсаны много где, поищите и обрящите приемлемый для себя вариант. Без этого - только рекурсия.
...
Рейтинг: 0 / 0
02.09.2003, 16:02
    #32253863
кам
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Если там всего пара сотен записей, то открываешь рекордсет с клиентским курсором, а по нему уже бегаешь. Хоть рекурсивно, хоть в цикле
...
Рейтинг: 0 / 0
02.09.2003, 16:17
    #32253881
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Даже без рекурсии, если в цикле пробегаю по записям такой функцией:

public function test(id as long)
dim rs as recordset
set rs = currentdb.openrecordset("table1")
rs.findfirst "idrec=" & id
test = rs!quantity
end function

то это происходит в несколько раз быстрее, чем такой

public function test(id as long)
dim rs as recordset
set rs = currentdb.openrecordset("table1")
rs.findfirst "idrec=" & id
test = rs!quantity
rs.close
set rs = nothing
end function

Странно...
Я здесь... Я там... Я всегда...
Пошел спать. Завтра к обеду думаться будет...
...
Рейтинг: 0 / 0
02.09.2003, 16:19
    #32253883
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
И ведь самое интересное: за каким я пробегаю в таком цикле по записям?..
Писец.
...
Рейтинг: 0 / 0
02.09.2003, 16:43
    #32253932
lobodava
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Можно ещё в каждой записи хранить полный путь до корня, например:
Страна/Область/Район/Город/Улица

Тогда выбрать ветку будет просто:

Код: plaintext
SELECT * FROM MyTable WHERE FullPath Like 'Страна/Область/Район/*';


Это, конечно, денормализация, но с ней жить легче :)
...
Рейтинг: 0 / 0
02.09.2003, 17:45
    #32254003
АлексейК
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
dllookup работает крайне медленно и лучше его избегать.
по возможности рекордсет лучше не создавать и не убивать в цикле а делать это один раз за выполнение кода.

я бы попробовал такую методику:
создать временную табличку с одним полем и скидывать в нее идентификаторы выбранной ветки до тех пор пока число записей не перестанет увеличиваться (проверять можно не каждый раз)

то есть сначала создать табличку с идентификатором начала ветки а затем циклически выполнять запрос вставки.

а потом запустить запрос вычисляющий сумму по идентификаторам во временной табличке.
...
Рейтинг: 0 / 0
04.09.2003, 12:07
    #32255676
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Был сильно с устатку, говорил ерунду. Я не суммирую ветку дерева.

Есть таблица чертежей. Любой чертеж может быть сборочным - содержать несколько вложенных чертежей. Скажем, чертеж на изготовление двух дверных петель. Каждая петля содержит по два одинаковых "уха" и стержень. Каждое "ухо" состоит из пластины и двух заклепок. Требуется узнать кол-во заклепок. 2 заклепки в "ухе" * 2 "уха" * 2 петли = 8 заклепок.

Есть отчет, в котором нужно сосчитать все несделанные детали на тек. момент. Он собирает детали без флажка "закончена" и потом с помощью функции на VBA по указанному алгоритму считает их количество (никаких рекурсий тут нет, это я с другой перепутал).

Так вот,
rs.close
set rs = nothing
дает чрезвычайно большую задержку выполнения. :(
...
Рейтинг: 0 / 0
04.09.2003, 12:31
    #32255718
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Табличка присоединенная?\r
\r
Но в любом случае открывать желательно DB, содержащую таблу, и гонять по ней Seek-ом. В Серверной - ваапще пройтись не в VBA, а курсором. Find - это в источнике-запросе, или в малой табле без индексов.\r
\r
по поводу rs.close - если открываешь несколько раз за подсчет - просто нехорошо (многократные дисковые операции - тут - чтение), и задержка может быть связана со всякими очистками кеша и повторным чтением (с {.close}, - против исспользования кеша без нее) и т.п.. \r
\r
Если нет (однократное открытие и закрытие таблы за _все_ время счета) - то очень похоже на вот эту проблему "закрытия" бд , которая, как ни странно, искуственно разрешается "упорядочиванием" (разделением по времени) обращения к различным объектам (даже сыроватый код /для 97/ вполне срабатывает, на порядки быстрее именно в части времени закрытия бд).
...
Рейтинг: 0 / 0
04.09.2003, 12:44
    #32255743
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
2assa
Табличка присоединенная, mdb + mdb.

Отрываю рекордсет 1 раз для одной строки запроса, ибо не уверен, что заполнять (опять же из вба) временную табличку будет быстрее, чем открывать/закрывать рекордсет.

Про "проблему "закрытия" бд" я помню, тем более, что я с тобой ее и обсуждал :), но она мне не кажется сильно похожей. Рекодсеты-то я открываю все-таки последовательно, а не одновременно.

Можно, конечно завести для этого запроса гл. переменную recordset, которую один раз открыть и закрыть "когда-нибудь потом", но это, имхо, очень кривой способ.
...
Рейтинг: 0 / 0
04.09.2003, 18:54
    #32256348
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
>>Отрываю рекордсет 1 раз для одной строки запроса

т.е. ф-я вызывается в запросе, и, в свою очередь, открывает рекордсет? Тогда "задержка" (в т.ч. при явном .close) - из-за затрат на чтение при каждом вызове. Это плёхо. Я так делал исключительно зная, что рекордсет (очень)маленький. //Интересно, что в этом случае, видимо, чтение (повторное) идет из кеша - судя по (малому) времени исполнения запросов с такой ф-ей//


т.ч. аккуратненько поюзать глобальный рекордсет и сразу закрыть - не самое последнее дело.
...
Рейтинг: 0 / 0
04.09.2003, 21:01
    #32256427
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
2assa
Ну что ж, попробую...
В понедельник поеду к этим товарищам, сделаю и во вторник выложу результаты.
Спасибо.
...
Рейтинг: 0 / 0
07.09.2003, 22:18
    #32257863
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Вот собственно.
Все проверил, количество считается уже после отбора чертежей (думал, м.б. когда писал, недоглядел), а их ок. 1000. И что, действительно открывать гл. переменную-рекордсет? А когда ее чистить? При закрытии отчета? Али сделать запрос каким-нибудь статическим и при форматировании, скажем, области данных?..
...
Рейтинг: 0 / 0
08.09.2003, 16:11
    #32258782
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Ойойой!
А что значит - слишком сложный запрос?!
...
Рейтинг: 0 / 0
08.09.2003, 16:27
    #32258817
Geo
Geo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Cуммирование ветки иерархического дерева
Усе. Получилось. Нафик все рекордсеты - сделал по другому. У меня стояло ограничение (зачем сделал - сам не знаю, сейчас вот пригодилось) на количество уровней вложенности. Сейчас сделал такой запросик:

SELECT tDrafts.NumDraft, nz([tDrafts].[Quantity],0) AS Quantity1, nz([tDrafts_1].[Quantity],1) AS Quantity2, nz([tDrafts_2].[Quantity],1) AS Quantity3, nz([tDrafts_3].[Quantity],1) AS Quantity4, nz([tDrafts_4].[Quantity],1) AS Quantity5, nz([tDrafts_5].[Quantity],1) AS Quantity6, nz([tDrafts_6].[Quantity],1) AS Quantity7, nz([tDrafts_7].[Quantity],1) AS Quantity8, nz([tDrafts_8].[Quantity],1) AS Quantity9, nz([tDrafts_9].[Quantity],1) AS Quantity10, nz([tDrafts_10].[Quantity],1) AS Quantity11
FROM (((((((((tDrafts LEFT JOIN tDrafts AS tDrafts_1 ON tDrafts.NumHighLevel = tDrafts_1.NumDraft) LEFT JOIN tDrafts AS tDrafts_2 ON tDrafts_1.NumHighLevel = tDrafts_2.NumDraft) LEFT JOIN tDrafts AS tDrafts_3 ON tDrafts_2.NumHighLevel = tDrafts_3.NumDraft) LEFT JOIN tDrafts AS tDrafts_4 ON tDrafts_3.NumHighLevel = tDrafts_4.NumDraft) LEFT JOIN tDrafts AS tDrafts_5 ON tDrafts_4.NumHighLevel = tDrafts_5.NumDraft) LEFT JOIN tDrafts AS tDrafts_6 ON tDrafts_5.NumHighLevel = tDrafts_6.NumDraft) LEFT JOIN tDrafts AS tDrafts_7 ON tDrafts_6.NumHighLevel = tDrafts_7.NumDraft) LEFT JOIN tDrafts AS tDrafts_8 ON tDrafts_7.NumHighLevel = tDrafts_8.NumDraft) LEFT JOIN tDrafts AS tDrafts_9 ON tDrafts_8.NumHighLevel = tDrafts_9.NumDraft) LEFT JOIN tDrafts AS tDrafts_10 ON tDrafts_9.NumHighLevel = tDrafts_10.NumDraft;

У них сейчас макс. уровень вложенности - 6-й, поставлю ограничение на 50.
5 раз этот запрос сам с собой связываю, потом перемножаю полученные поля - 3 сек. на 3000 записей (против 5 или 70 на 1000). Нормально. Всем спасибо.
...
Рейтинг: 0 / 0
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Cуммирование ветки иерархического дерева / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]