Почему в запросе к регистру бухгалтерии появляются дубли и как их устранить

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет Промышленность, строительство и АПК
← На главную

При разработке сложных отчетов в системе 1С:Предприятие 8 программисты часто сталкиваются с проблемой «размножения» строк. Ситуация, когда одно и то же основное средство или объект строительства выводится в отчете несколько раз с одинаковыми суммами, может запутать пользователя и привести к неверным итоговым данным. В этой статье мы подробно разберем, почему возникают такие ситуации при работе с виртуальными таблицами регистра бухгалтерии, и как правильно структурировать запрос, чтобы избежать дублей.

Анализ исходной проблемы

Рассмотрим ситуацию, описанную в теме. Автор использует виртуальную таблицу РегистрБухгалтерии.Хозрасчетный.Обороты для получения данных по объектам строительства (счет 08) в корреспондеции с основными средствами (счет 01). В запросе также задействованы левые соединения с табличной частью объекта и регистром сведений. В результате в отчете для одного основного средства выводится несколько строк.

Выясним причину такого поведения системы. Основная сложность заключается в том, что дубли могут возникать на трех разных этапах формирования выборки:

  1. На уровне виртуальной таблицы оборотов при наличии сложной корреспонденции.
  2. При обращении к табличным частям объектов через точку.
  3. При неполном соответствии измерений в соединении с регистром сведений.

Решение 1: Обработка табличных частей в запросе

Одной из самых неочевидных причин дублирования является конструкция ДляОтбора.ОсновноеСредство.ИнформацияОТрубопроводе.(...). В 1С обращение к вложенной таблице (табличной части) в списке полей выбора работает как неявное соединение. Если у одного основного средства в табличной части ИнформацияОТрубопроводе заполнено, к примеру, 5 строк, то в итоговом результате запроса вся информация по этому основному средству (включая бухгалтерские обороты) продублируется 5 раз.

Рассмотрим правильный подход:

Вместо прямого обращения к табличной части через точку в основном запросе, следует вынести данные табличной части во временную таблицу, предварительно их сгруппировав или отобрав только нужные значения. Проанализируем пример кода для подготовки данных:


ВЫБРАТЬ
    Трубопроводы.Ссылка КАК ОсновноеСредство,
    МАКСИМУМ(Трубопроводы.Давление) КАК Давление,
    СУММА(Трубопроводы.Длина) КАК ОбщаяДлина
ПОМЕСТИТЬ ВТ_ПараметрыТрубопровода
ИЗ
    Справочник.ОсновныеСредства.ИнформацияОТрубопроводе КАК Трубопроводы
ГДЕ
    Трубопроводы.Ссылка В (ВЫБРАТЬ ОсновноеСредство ИЗ ДляОтбора)
СГРУППИРОВАТЬ ПО
    Трубопроводы.Ссылка;

После того как данные свернуты до одной строки на объект, их можно безопасно соединять с основным результатом запроса.

Решение 2: Группировка данных в СКД и запросе

Если отчет строится с использованием Системы компоновки данных (СКД), проблему часто удается решить на уровне настроек группировок. Когда мы выводим детальные записи без указания группировок, СКД выводит все строки, которые вернул SQL-запрос. Как только мы добавляем группировку по полю ОсновноеСредство, система начинает агрегировать данные.

Однако полагаться только на СКД не всегда верно. Если в запросе есть суммовые показатели (например, СуммаОборот), и из-за дублей они увеличились в несколько раз, простая группировка в СКД может скрыть дубли строк, но оставить неверные итоги. Поэтому проанализируем ситуацию в самом тексте запроса и добавим явную группировку:


ВЫБРАТЬ
    ХозрасчетныйОбороты.Субконто1 КАК ОбъектСтроительства,
    ХозрасчетныйОбороты.КорСубконто1 КАК ОсновноеСредство,
    СУММА(ХозрасчетныйОбороты.СуммаОборот) КАК СуммаОборот
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Обороты(&ДатаНачала, &ДатаОкончания, , Счет В ИЕРАРХИИ (&Счет08), , , КорСчет В ИЕРАРХИИ (&КорСчет01), ) КАК ХозрасчетныйОбороты
СГРУППИРОВАТЬ ПО
    ХозрасчетныйОбороты.Субконто1,
    ХозрасчетныйОбороты.КорСубконто1;

Это гарантирует нам, что из регистра бухгалтерии мы получим уникальные пары «Объект - Основное средство» с корректно рассчитанными суммами.

Решение 3: Проверка соединений с регистрами сведений

При использовании таблицы СрезПоследних часто возникает заблуждение, что она всегда возвращает одну строку. Это верно только в том случае, если в соединении (условие ПО) задействованы все измерения регистра.

Разберем пример из темы. Если в регистре ВОГ_ПротяженностьГазопроводов_ОС помимо измерения ОсновноеСредство есть, например, измерение Организация или ВидТрубопровода, то срез последних вернет по одной записи на каждую комбинацию этих измерений. Если в запросе связь идет только по полю ОсновноеСредство, мы получим столько строк, сколько уникальных комбинаций измерений существует в регистре для данного объекта.

Посмотрим на метод исправления:

  1. Проверьте структуру регистра сведений в конфигураторе.
  2. Если измерений несколько, добавьте их в условия связи: ПО ДляОтбора.ОсновноеСредство = Срез.ОсновноеСредство И ДляОтбора.Организация = Срез.Организация.
  3. Если дополнительные измерения не важны для отчета, предварительно выберите данные из регистра во временную таблицу, используя СГРУППИРОВАТЬ ПО ОсновноеСредство и выбрав максимальные или средние значения ресурсов.

Декомпозиция запроса для поиска ошибки

Если причина дублей всё еще не ясна, применим методику декомпозиции, которую рекомендуют опытные разработчики. Разберем запрос по шагам:

Шаг 1. Оставьте в запросе только обращение к виртуальной таблице оборотов. Проверьте количество строк. Если их больше, чем ожидалось, проблема в параметрах виртуальной таблицы или в данных самого регистра (например, несколько проводок по одним и тем же субконто).

Шаг 2. Последовательно добавляйте по одному соединению. Сначала добавьте связь с регистром сведений. Если количество строк увеличилось — значит, связь идет не по всем измерениям или в регистре есть неоднозначность.

Шаг 3. В последнюю очередь добавляйте обращения к реквизитам через точку. Это самый «дорогой» и опасный с точки зрения дублей механизм.

Важный нюанс: Использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ вместо ЛЕВОЕ СОЕДИНЕНИЕ не избавляет от дублей. Внутреннее соединение просто отсекает те строки, для которых нет соответствия в правой таблице, но если в правой таблице для одной записи левой нашлось две подходящих — в результате всё равно будет две строки.

Используя эти методы, мы сможем построить чистый и эффективный запрос, который будет возвращать корректные данные без лишней избыточности.

← На главную