В практике разработки на платформе 1С часто возникает задача получения остатков не на одну конкретную дату (что легко решается стандартными параметрами виртуальной таблицы), а на целый список произвольных дат. Например, когда нужно построить отчет по остаткам на каждый день месяца или на даты определенных событий. Стандартная виртуальная таблица Остатки регистра бухгалтерии не позволяет передать массив дат в параметры, поэтому нам необходимо использовать альтернативные подходы.
В этой статье мы рассмотрим несколько эффективных способов решения данной задачи, проанализируем их производительность и разберем технические нюансы реализации.
Это один из самых простых и в то же время эффективных способов, особенно если результат нужно вывести в виде отчета. Система компоновки данных обладает встроенными механизмами для работы с периодами.
Разберем по шагам, как настроить получение остатков на каждый день или по списку дат:
ОстаткиИОбороты.Период в настройках набора данных (колонка "Роль") укажем тип "Период" и выставим соответствующую периодичность (например, День).Преимущество этого метода заключается в том, что платформа берет на себя сложный расчет итогов "на лету", обеспечивая при этом приемлемую скорость работы в большинстве типовых конфигураций, таких как 1С:Бухгалтерия 2.0.
Если нам необходимо получить данные именно программно в коде запроса, рассмотрим метод накопленного итога. Этот способ считается наиболее производительным при работе с большим массивом дат, так как он минимизирует количество обращений к таблице итогов.
Проанализируем алгоритм реализации:
ВТ_Даты, в которую поместим наш список произвольных дат. Обязательно проиндексируем поле Дата.ВТ_Даты с таблицей оборотов по условию Обороты.Период <= ВТ_Даты.Дата.Пример структуры такого запроса:
ВЫБРАТЬ
Т_Даты.Дата КАК Период,
ЕСТЬNULL(НачОстатки.СуммаОстатокДт, 0) + СУММА(ЕСТЬNULL(Обороты.СуммаОборотДт, 0) - ЕСТЬNULL(Обороты.СуммаОборотКт, 0)) КАК ОстатокНаДату
ИЗ
ВТ_Даты КАК Т_Даты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(&НачалоПериода, Счет = &НужныйСчет) КАК НачОстатки ПО ИСТИНА
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Обороты(&НачалоПериода, &КонецПериода, День, Счет = &НужныйСчет) КАК Обороты
ПО Обороты.Период <= Т_Даты.Дата
ГРУППИРОВАТЬ ПО
Т_Даты.Дата,
НачОстатки.СуммаОстатокДт
Если дат в списке немного (например, 3-5), иногда проще и быстрее выполнить запрос в цикле или использовать пакетный запрос с несколькими обращениями к виртуальной таблице Остатки. Рассмотрим ситуацию, когда мы передаем конкретную дату в параметр таблицы.
Важно помнить: 1С не позволяет передать значение поля одной таблицы в параметр виртуальной таблицы другой таблицы в рамках одного запроса. Поэтому код вида ЛЕВОЕ СОЕДИНЕНИЕ Регистр.Остатки(Т_Даты.Дата) не сработает. Нам придется либо использовать временные таблицы для каждой даты, либо выполнять расчет через соединение с таблицей движений, фильтруя их по условию ГДЕ.
Выясним, почему некоторые запросы работают медленно и как это исправить:
Остатки рассчитывает данные от ближайшей точки хранения итогов (обычно начало месяца). Если вы запрашиваете остатки на 31 число каждого дня месяца через тяжелое соединение, система может выполнить 31 полноценный расчет. Для оптимизации всегда старайтесь ограничивать выборку конкретными счетами и субконто внутри параметров виртуальной таблицы.ЕСТЬNULL. Если на определенную дату движений не было, запрос вернет NULL, что при сложении с числами даст пустой результат.КОНЕЦПЕРИОДА(НужнаяДата, ДЕНЬ), либо использовать объект Граница с включением моментов времени последних документов дня.Таким образом, для простых отчетов оптимальным выбором будет СКД с дополнением периодов, а для сложных алгоритмов внутри обработок — запрос с накопленным итогом через таблицу оборотов.