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

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

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

rst.close
set rst = nothing

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

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

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

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
Cуммирование ветки иерархического дерева
    #32253883
Фотография Geo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И ведь самое интересное: за каким я пробегаю в таком цикле по записям?..
Писец.
...
Рейтинг: 0 / 0
Cуммирование ветки иерархического дерева
    #32253932
lobodava
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ещё в каждой записи хранить полный путь до корня, например:
Страна/Область/Район/Город/Улица

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

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


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

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

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

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

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

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

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

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

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

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

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


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

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
17 сообщений из 17, страница 1 из 1
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Cуммирование ветки иерархического дерева
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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