В стандартных задачах 1С получение остатков обычно привязано к стандартным периодам: начало дня, месяца или текущий момент. Однако на производстве или в рознице часто возникает потребность получить остатки на границы смен, которые могут не совпадать с началом часа или дня (например, 06:45, 15:30, 23:00). Рассмотрим основные способы решения этой задачи, проанализируем их эффективность и разберем конкретные примеры реализации.
Один из самых распространенных подходов заключается в предварительном формировании таблицы всех необходимых моментов времени (контрольных точек), на которые нужно получить остатки. Рассмотрим этот алгоритм подробнее:
ОстаткиИОбороты. Здесь есть важный нюанс: при получении данных на произвольные моменты времени внутри дня необходимо использовать периодичность ПериодСекунда.Рассмотрим пример кода для формирования такой таблицы:
// Пример заполнения таблицы контрольных точек (смен)
ТЗСмен = Новый ТаблицаЗначений;
ТЗСмен.Колонки.Добавить("Период", Новый ОписаниеТипов("Дата"));
// Заполняем ТЗ нужными датами (например, в цикле по дням периода)
// Для каждой даты добавляем время: 06:45, 15:30, 23:00
НоваяСтрока = ТЗСмен.Добавить();
НоваяСтрока.Период = ДатаГраницыСмени;
// Далее передаем ТЗ в запрос как временную таблицу
В самом запросе мы используем левое соединение таблицы дат с таблицей регистра. Проанализируем ситуацию: если мы просто обратимся к виртуальной таблице Остатки, передавая период в параметрах связи, система может работать медленно, так как будет выполнять вложенный запрос для каждой строки. Поэтому эффективнее использовать таблицу движений или оборотов с детализацией по секундам.
Если количество контрольных точек (смен) не слишком велико, можно применить метод генерации текста запроса. Проанализируем этот способ: мы в цикле создаем фрагменты запроса, каждый из которых получает остаток на конкретную дату, и объединяем их через оператор ОБЪЕДИНИТЬ ВСЕ.
Преимущества: система отрабатывает каждый блок максимально быстро, обращаясь к итогам на конкретный момент времени.
Недостатки: при большом количестве смен (например, за год) текст запроса станет огромным, что может привести к ошибке переполнения стека парзера SQL или просто к зависанию при компиляции запроса.
Для достижения максимальной производительности на больших объемах данных рекомендуется использовать расчет остатков «с нуля» через сумму движений или комбинированный метод. Разберем по шагам наиболее эффективную схему:
Остатки.Обороты.Период <= КонтрольнаяТочка.Период.Этот метод исключает многократное сканирование итогов базы данных, которое происходит при каждом обращении к виртуальной таблице остатков в цикле или соединении.
При реализации любого из методов следует учитывать следующие особенности платформы 1С:
МоментВремени. Доступна только точность до секунды. Если движение и граница смены приходятся на одну и ту же секунду, используйте условие <= или < в зависимости от того, должно ли движение этой секунды войти в смену.ОстаткиИОбороты параметр Периодичность должен иметь значение Период или ПериодСекунда, чтобы данные не схлопывались до начала дня.Запрос.Выполнить() внутри цикла Для) работает в сотни раз медленнее, чем один сложный запрос. Всегда стремитесь перенести логику на сторону SQL-сервера.Таким образом, для получения остатков на концы смен оптимальным является использование временной таблицы дат, проиндексированной и соединенной с физической таблицей регистра или виртуальной таблицей оборотов с высокой детализацией. Это обеспечит баланс между скоростью разработки и производительностью системы.