При разработке отчетов и запросов в 1С часто возникает задача получить остатки по регистру бухгалтерского учета или накопления на каждую дату заданного интервала. Начинающие разработчики пытаются подставить поле с датой из временной таблицы (например, из производственного календаря) прямо в параметр виртуальной таблицы, такой как Остатки(&КонецПериода, ...). Проанализируем ограничения платформы 1С и разберем правильные способы решения этой задачи.
В языке запросов 1С параметры виртуальных таблиц (Остатки, СрезПоследних, ОстаткиИОбороты и др.)принимают строго определенные типы значений:
&, например, &НачалоПериода).Передать значение из поля другой таблицы или временной таблицы (например, ДниКалендаря.Дата) в параметр виртуальной таблицы невозможно. Платформа 1С формирует один SQL-запрос к СУБД, и параметры виртуальных таблиц преобразуются в подзапросы или условия на уровне базы данных. Внутри одного запроса механизм параметризации виртуальных таблиц для каждой строки внешнего источника не предусмотрен.
Рассмотрим стандартный алгоритм построения остатков на каждую дату периода. Для этого мы сначала создаем таблицу дат (календарь), а затем соединяем ее с данными регистра.
Разберем по шагам логику построения такого запроса:
Дни.ОстаткиИОбороты с периодичностью День.Период <= Дата и суммируем показатели.Рассмотрим пример готового запроса для расчета остатков по счету расчетов:
ВЫБРАТЬ
ДанныеПроизводственногоКалендаря.Дата КАК Дата
ПОМЕСТИТЬ Дни
ИЗ
РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеПроизводственногоКалендаря
ГДЕ
ДанныеПроизводственногоКалендаря.Дата МЕЖДУ &НачалоПериода И &КонецПериода
ИНДЕКСИРОВАТЬ ПО
Дата
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Дни.Дата КАК Дата,
ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Контрагент,
ХозрасчетныйОстаткиИОбороты.Субконто2 КАК Договор,
СУММА(ВЫБОР
КОГДА ХозрасчетныйОстаткиИОбороты.Период = &НачалоПериода
ТОГДА ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстаток
ИНАЧЕ ВЫБОР
КОГДА ХозрасчетныйОстаткиИОбороты.Период <= Дни.Дата
ТОГДА ХозрасчетныйОстаткиИОбороты.СуммаОборот
ИНАЧЕ 0
КОНЕЦ
КОНЕЦ) КАК СуммаОстаток
ИЗ
Дни КАК Дни,
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , Счет = &Счет, , ) КАК ХозрасчетныйОстаткиИОбороты
СГРУППИРОВАТЬ ПО
Дни.Дата,
ХозрасчетныйОстаткиИОбороты.Субконто1,
ХозрасчетныйОстаткиИОбороты.Субконто2
УПОРЯДОЧИТЬ ПО
Контрагент,
Договор,
Дата
Важные детали реализации:
Инструкция ИНДЕКСИРОВАТЬ ПО Дата при создании временной таблицы критически важна для производительности, так как соединение выполняется по условию неравенства (<=).
Если отчет разрабатывается на Системе компоновки данных, решать задачу соединения таблиц вручную в запросе не требуется. В СКД есть два встроенных механизма для работы с остатками на каждый день:
Период, Начальный остаток и Конечный остаток. В настройках группировки периода указывается тип дополнения День. СКД автоматически рассчитает входящие и исходящие остатки на каждый день, даже если за эти даты не было движений.Остатки(&Период). На вкладке Связи наборов данных значение даты из первого набора передается в параметр &Период второго набора. В этом случае СКД выполнит запрос к виртуальной таблице для каждой даты автоматически.Выясним основные причины, из-за которых расчет остатков по датам может выводить некорректные данные:
Период = Дата приводит к тому, что дни без оборотов выпадают из выборки или содержат пустые остатки.СУММА() строки дублируются, а остатки умножаются на количество совпавших дат.&НачалоПериода и прибавлять к нему обороты последующих дней.