|
|
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
Чуть меньше года назад, буквально только-только занявшись аццессом, нарисовал программку складского учета и торговли. Понадеявшись на почти фантастическую скорость расчетов с БД у Аццесса, все остатки у меня считаются в он-лайне при формировании какой-нибудь расходной накладной. Соответственно, по прошествии времени на одном из предприятий накопились сотни тысяч записей прихода и расхода (ах, да, в программе реализован партионный учет, что тоже неслабо влияет на быстродействие), как следствие пересчет остатков занимает уже порядка полутора минут. Это конечно неправильно. Сейчас вот решил (вернее, решил уже давно, сейчас решил начать:), пользуясь багажом полученных здесь и у г-на Гетца новых знаний переписать программу. На всякий случай задам довольно концептуальный вопрос. Зачем нужны остатки. Конечно, для отчетов, где скорость в принципе не важна, плюс для проверки невозможности отпуска товара, которого на складе(ах) нет или недостаточно. Я обычно для ускорения пересчета остатков пользуюсь одним из следующих методов: 1. Запрещать изменения не последней записи. В этом случае просто держу временную табличку со всеми текущими (на момент, следующий за последней записью) остатками - рассчитывать ничего не надо, остатки всегда есть. Недостатки метода налицо. 2. "Закрыть период". В конце дня/недели/месяца/квартала "закрываю период". Создается запись остатков на конец периода. Все расчеты ведутся от этой записи. Чем больше движение, тем меньше нужен период для быстрых расчетов. Недостатки: редко, и, казалось бы, не совсем "по закону", но бухгалтерии иногда требуется что-нибудь менять задним числом. Естественно, после закрытия периода я запрещаю все изменения. 3. "Инвентаризация". Некий композит из методов 1 и 2. Т.е. закрытием периода является момент инвентаризации. Остатки на начало периода - также запись инвентаризации. Недостатки те же, что в п. 2 + п. 4. 4. Считать остатки "динамически". Т.е. "с начала времен". Очевидные плюсы - можно править приход/расход в любой и за любой момент времени. Минусы - с ростом базы скорость расчета катастрофически падает. Здесь небольшое лирическое отступление. П. 4. можно реализовывать с вариациями - при вводе расходной накладной мы можем либо сразу расчитать все остатки по всем партиям всех товаров, что тормознет систему при начале заполнения накладной, либо рассчитывать остатки по конкретной партии конкретного товара, что, конечно, хорошо, но надолго ли? Вот, кажется, и все. Поделитесь, пожалуйста, своим опытом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 18:54 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
У меня есть табличка с текущими остатками по складам. В процессе добавления/изменения\удаления материалов правятся текущие остатки. У меня это реализовано в виде триггеров (база на SQL), в Аксеесе нужно будет писать на клиенте, плюс, скорее всего, потребуется программа сверки, которую нужно будет запускать в нерабочее время для выявления ошибок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:04 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
держу таблицу Остатки, в которой остатки текущие. При выписке накладный остатки правятся "на лету". Собственно все. При необходимости можно сравнить остатки с движением и сделать необходимые выводы о работе программы. А в чем собственно недостатки? пункт 2. Предлагаю поднять тему в понедельник. ибо пора домой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:05 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
Предлагаю поднять тему в понедельник. ибо пора домой. Да мне, в принципе, не к спеху, но найденный ответ, думаю, мог бы пригодиться всем. 2Nick987 и sasha_1 Это вроде бы правильно. Но. Предположим такую ситуацию: на складе на 01.01.2001 нет апельсинов. Кто-нибудь берет и задним числом (01.01.2001) ставит расход на n кг этих самых апельсинов. Это нехорошо. Если уж мы разрешаем изменять приход/расход задним числом, то нужно хотя бы контролировать политкорректность этих изменений. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:10 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
Тут два варианта: либо запретить изменения задним числом (что логично - историю не правим), либо при подобной проводке считать остатки на тот момент от начала времен и тут уж на скорость пусть не жалуются :-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:14 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
если считать "динамически" - пересчет всей базы не нужен. нужно только добавлять, складыать. вычитать. Проблема Акеса - нет триггеров. Поэтому обрабатывать любое изменение во всех модифицирующих данные интерфейсах. (добавление, изменение (Value-oldValue), вставка). Проблема в том, что эти функции обязаны точно срабатывать ВСЕГДА (никаких "on error resume next"). В том числе, если пользователь по десять раз входит/выходит в поля, нажимает esc (в т.ч. - на отмену встаки всей записи) и т.п. При некорректном завершении работы (по разным причинам) нужна сервисная функция пересчета текущих остатков (можно, например, при начальной загрузке). ЗЫ. в так называемом RS-Balans (Btriev) остатки велись в 13 полях - 12 месяцев +текущий - чтобы считать отчеты на любой момент времени за приемлемое время. Сервисное восстановление целостности могло занимать десятки минут. (если развернутая учетная аналитика). Правда связь с ЦБ там была кривой (именно реализация, а не логика), и на больших объемах склад вести в нем не имело смысла - из-за проблем выгрузки проводок в ЦБ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:18 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
2Nick987 Предыдущая описанная мной ситуация была хотя и возможна, но не слишком часто встречающаяся. Теперь другая, встречающаяся сплошь и рядом. Нужно поправить предыдущий расход (например, случайно указали товар не из той партии). Это не последняя запись - так что считаем остатки с "начала времен". Тоже не есть хорошо. Поначалу я пошел именно таким путем - сделал заплатку на программу, которая так и боролась за высокое быстродействие. Как выяснилось, помогает она примерно в половине случаев. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:19 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
2assa Очень интересный способ. Не слишком простая реализация, но очень неплохо! Сейчас припоминаю, что где-то уже видел аналогичное, но, к сожалению, не помню, где :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:23 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
2 GEo Можно и от конца считать, при условии регулярного запуска программы сверки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:28 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
ДА, а считаешь остатки ("при заполнении накладной") по всей номенклатуре или только по позиции? Если по позиции, и записей по каждой позиции<< чем по всей номенклатуре, правильно составленные индексы должны помочь. (время будет падать в разы, опять таки правильно выделить часть WHERE запросов, и поменьше пользоваться тупо вставляемым акесом HAVING) И какое-то время можно не заморачиваться с "денормализацией" и синхронизацией агрегатов. Минусовые остатки можно разрешить, - и все вопросы по ним к менеджеру. Пусть сводят балансы в +. Хотя как-то я писал "кассовую книгу" с пересчетом остаков (остаток за день) за все "будущие" периоды от момента вставки. Но там "позиция" одна -"деньги". Т.ч. считать требовалось просто - по всем записям. Но я просто добавлял или вычитал дельту к расчитанным дням. Вроде работало. Но это халтура, есс-но. ТАм бабки как картошку кидали. Требовалось, чтобы все батонами вводилось. По возможности в тупом цикле, без всяких там мышек и выпадающих списков. (и если уж выпадал -то шоб сам переходил на следующую позицию (значение по умолчанию) при смене записи). ну и т.п. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 19:54 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
а считаешь остатки ("при заполнении накладной") по всей номенклатуре или только по позиции В программе, о которой завел речь, я "сразу расчитываю все остатки по всем партиям всех товаров". Вот что я подумал по поводу предложенного тобой метода после 2-х пив: Cтруктура записи приход/расход: IdЗаписи/IdНакладной/IdТовара/Цена/Количество/HiddenКолвоПред Структура записи "остатков на конец периода" IdТовара/Колво Что получается: 1. При вводе новой записи товара - HiddenКолвоПред = 0. При изменении записи прихода/расхода HiddenКолвоПред = Количество. Количество = новое значение. 2. При любом вызове пересчета остатков на любую дату пересчитываются все изменения (! - не движение, а только дельты, а их может и не быть) остатков товаров. Что имеем: Время расчета остатков будет расти от момента начала периода до его окончания. И, только в случае массовых правок движения товаров задним числом, будет заметное замедление расчета. Минусы: Довольно сложные алгоритмы расчетов. И (вроде бы) все. Но, разве нас не учили, что настоящий пионер/комсомолец/коммунист даже малую нужду должен справлять против ветра? Прорвемся :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 22:02 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
Ошибка, следует читать: Структура записи "остатков на конец периода" ДатаНачалаПериода/IdТовара/Колво ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 22:05 |
|
||
|
Текущие остатки
|
|||
|---|---|---|---|
|
#18+
Люблю способ 2. "Закрыть период" - туева туча записей, а считаються только открытые. Наверное идиален для Mdb (проблемы "заднее число" у меня не наблюдалсь). На SQL-сервере - лучше (ИМХО) держать таблицу расчитанных остатков. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2003, 23:01 |
|
||
|
|

start [/forum/moderation_log.php?user_name=vidoq]: |
0ms |
get settings: |
5ms |
get forum list: |
10ms |
get settings: |
8ms |
get forum list: |
19ms |
get settings: |
11ms |
get forum list: |
18ms |
get settings: |
9ms |
get forum list: |
21ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
53ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
45ms |
get tp. blocked users: |
1ms |
| others: | 5664ms |
| total: | 5905ms |

| 0 / 0 |
