При разработке сложных отчетов в системе 1С:Предприятие 8 программисты часто сталкиваются с проблемой «размножения» строк. Ситуация, когда одно и то же основное средство или объект строительства выводится в отчете несколько раз с одинаковыми суммами, может запутать пользователя и привести к неверным итоговым данным. В этой статье мы подробно разберем, почему возникают такие ситуации при работе с виртуальными таблицами регистра бухгалтерии, и как правильно структурировать запрос, чтобы избежать дублей.
Рассмотрим ситуацию, описанную в теме. Автор использует виртуальную таблицу РегистрБухгалтерии.Хозрасчетный.Обороты для получения данных по объектам строительства (счет 08) в корреспондеции с основными средствами (счет 01). В запросе также задействованы левые соединения с табличной частью объекта и регистром сведений. В результате в отчете для одного основного средства выводится несколько строк.
Выясним причину такого поведения системы. Основная сложность заключается в том, что дубли могут возникать на трех разных этапах формирования выборки:
Одной из самых неочевидных причин дублирования является конструкция ДляОтбора.ОсновноеСредство.ИнформацияОТрубопроводе.(...). В 1С обращение к вложенной таблице (табличной части) в списке полей выбора работает как неявное соединение. Если у одного основного средства в табличной части ИнформацияОТрубопроводе заполнено, к примеру, 5 строк, то в итоговом результате запроса вся информация по этому основному средству (включая бухгалтерские обороты) продублируется 5 раз.
Рассмотрим правильный подход:
Вместо прямого обращения к табличной части через точку в основном запросе, следует вынести данные табличной части во временную таблицу, предварительно их сгруппировав или отобрав только нужные значения. Проанализируем пример кода для подготовки данных:
ВЫБРАТЬ
Трубопроводы.Ссылка КАК ОсновноеСредство,
МАКСИМУМ(Трубопроводы.Давление) КАК Давление,
СУММА(Трубопроводы.Длина) КАК ОбщаяДлина
ПОМЕСТИТЬ ВТ_ПараметрыТрубопровода
ИЗ
Справочник.ОсновныеСредства.ИнформацияОТрубопроводе КАК Трубопроводы
ГДЕ
Трубопроводы.Ссылка В (ВЫБРАТЬ ОсновноеСредство ИЗ ДляОтбора)
СГРУППИРОВАТЬ ПО
Трубопроводы.Ссылка;
После того как данные свернуты до одной строки на объект, их можно безопасно соединять с основным результатом запроса.
Если отчет строится с использованием Системы компоновки данных (СКД), проблему часто удается решить на уровне настроек группировок. Когда мы выводим детальные записи без указания группировок, СКД выводит все строки, которые вернул SQL-запрос. Как только мы добавляем группировку по полю ОсновноеСредство, система начинает агрегировать данные.
Однако полагаться только на СКД не всегда верно. Если в запросе есть суммовые показатели (например, СуммаОборот), и из-за дублей они увеличились в несколько раз, простая группировка в СКД может скрыть дубли строк, но оставить неверные итоги. Поэтому проанализируем ситуацию в самом тексте запроса и добавим явную группировку:
ВЫБРАТЬ
ХозрасчетныйОбороты.Субконто1 КАК ОбъектСтроительства,
ХозрасчетныйОбороты.КорСубконто1 КАК ОсновноеСредство,
СУММА(ХозрасчетныйОбороты.СуммаОборот) КАК СуммаОборот
ИЗ
РегистрБухгалтерии.Хозрасчетный.Обороты(&ДатаНачала, &ДатаОкончания, , Счет В ИЕРАРХИИ (&Счет08), , , КорСчет В ИЕРАРХИИ (&КорСчет01), ) КАК ХозрасчетныйОбороты
СГРУППИРОВАТЬ ПО
ХозрасчетныйОбороты.Субконто1,
ХозрасчетныйОбороты.КорСубконто1;
Это гарантирует нам, что из регистра бухгалтерии мы получим уникальные пары «Объект - Основное средство» с корректно рассчитанными суммами.
При использовании таблицы СрезПоследних часто возникает заблуждение, что она всегда возвращает одну строку. Это верно только в том случае, если в соединении (условие ПО) задействованы все измерения регистра.
Разберем пример из темы. Если в регистре ВОГ_ПротяженностьГазопроводов_ОС помимо измерения ОсновноеСредство есть, например, измерение Организация или ВидТрубопровода, то срез последних вернет по одной записи на каждую комбинацию этих измерений. Если в запросе связь идет только по полю ОсновноеСредство, мы получим столько строк, сколько уникальных комбинаций измерений существует в регистре для данного объекта.
Посмотрим на метод исправления:
ПО ДляОтбора.ОсновноеСредство = Срез.ОсновноеСредство И ДляОтбора.Организация = Срез.Организация.СГРУППИРОВАТЬ ПО ОсновноеСредство и выбрав максимальные или средние значения ресурсов.Если причина дублей всё еще не ясна, применим методику декомпозиции, которую рекомендуют опытные разработчики. Разберем запрос по шагам:
Шаг 1. Оставьте в запросе только обращение к виртуальной таблице оборотов. Проверьте количество строк. Если их больше, чем ожидалось, проблема в параметрах виртуальной таблицы или в данных самого регистра (например, несколько проводок по одним и тем же субконто).
Шаг 2. Последовательно добавляйте по одному соединению. Сначала добавьте связь с регистром сведений. Если количество строк увеличилось — значит, связь идет не по всем измерениям или в регистре есть неоднозначность.
Шаг 3. В последнюю очередь добавляйте обращения к реквизитам через точку. Это самый «дорогой» и опасный с точки зрения дублей механизм.
Важный нюанс: Использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ вместо ЛЕВОЕ СОЕДИНЕНИЕ не избавляет от дублей. Внутреннее соединение просто отсекает те строки, для которых нет соответствия в правой таблице, но если в правой таблице для одной записи левой нашлось две подходящих — в результате всё равно будет две строки.
Используя эти методы, мы сможем построить чистый и эффективный запрос, который будет возвращать корректные данные без лишней избыточности.