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