В процессе разработки систем автоматизации на платформе 1С:Предприятие часто возникает необходимость списания партий товаров по методу FIFO (первым пришел — первым ушел). Задача усложняется, когда требуется выбрать не фиксированное количество записей, а ровно столько партий, сколько необходимо для покрытия заданного количества товара (например, 8 единиц). Давайте разберем, как решить эту задачу в рамках языка запросов и когда стоит предпочесть другие методы.
Поскольку язык запросов 1С не поддерживает стандартные оконные функции, нам приходится прибегать к приему самосоединения (self-join). Суть метода заключается в соединении таблицы самой с собой по условию, которое позволяет суммировать количество записей, предшествующих текущей по времени.
Для реализации этого подхода выполним следующие шаги:
ИМЕЮЩИЕ для отсечения партий, которые превышают нужный лимит (в нашем примере — 8 единиц).Посмотрим на пример кода для реализации этой логики:
ВЫБРАТЬ
ПартииТоваровКомпанииОстатки.Партия.МоментВремени КАК ПартияМоментВремени,
ПартииТоваровКомпанииОстатки.КоличествоОстаток КАК КоличествоОстаток,
ПартииТоваровКомпанииОстатки.СуммаОстаток КАК СуммаОстаток
ПОМЕСТИТЬ втПартии
ИЗ
РегистрНакопления.ПартииТоваровКомпании.Остатки(&МоментСреза, Номенклатура = &Номенклатура И СкладКомпании = &СкладКомпании) КАК ПартииТоваровКомпанииОстатки
;
ВЫБРАТЬ
втПартии.ПартияМоментВремени КАК ПартияМоментВремени,
втПартии.КоличествоОстаток КАК КоличествоОстаток,
втПартии.СуммаОстаток КАК СуммаОстаток,
СУММА(втПартииНарастающее.КоличествоОстаток) КАК КоличествоНарастающийИтог
ИЗ
втПартии КАК втПартии
ВНУТРЕННЕЕ СОЕДИНЕНИЕ втПартии КАК втПартииНарастающее
ПО (втПартии.ПартияМоментВремени >= втПартииНарастающее.ПартияМоментВремени)
СГРУППИРОВАТЬ ПО
втПартии.ПартияМоментВремени,
втПартии.КоличествоОстаток,
втПартии.СуммаОстаток
ИМЕЮЩИЕ
СУММА(втПартииНарастающее.КоличествоОстаток) - втПартии.КоличествоОстаток <= 8
Рассмотренный выше запрос является классическим решением, однако мы должны помнить о производительности. Операция самосоединения («каждый с каждым») имеет квадратичную сложность. Если в регистре накопились тысячи партий, такой запрос может работать крайне медленно и блокировать таблицы базы данных.
Рассмотрим более предпочтительный вариант — пост-обработку в коде 1С. Этот метод гораздо проще в отладке и часто работает быстрее:
МоментуВремени.Счетчик.Счетчик превысит нужное нам значение (8 единиц), мы прерываем цикл оператором Прервать.Преимущества работы в коде очевидны: мы избавляем сервер базы данных от тяжелых вычислений, передавая всю логику на уровень исполнения кода 1С. Это стандартная практика при списании партий, когда необходимо обеспечить максимальную скорость работы документа при проведении.
При выборе метода всегда задавайтесь вопросом об объемах данных:
Партия.МоментВремени).Помните, что в типовых конфигурациях (например, 1С:Управление торговлей) партионный учет обычно реализован через механизмы, которые рассчитывают списания в момент проведения документа, что позволяет избегать подобных сложных запросов в аналитических отчетах.