Как в запросе 1С связать Авансовый отчет с Этапом производства через Заказ на производство?

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

В типовых конфигурациях, таких как 1С:ERP Управление предприятием или 1С:Комплексная автоматизация, часто возникает необходимость кастомизации сложных отчетов, например, «Движение материалов и продукции». Типичная задача — вывести информацию об авансовых отчетах в иерархии производственных затрат. Однако из-за сложности структуры метаданных и огромного объема типовых запросов программисты часто сталкиваются с ситуацией, когда данные из основной таблицы начинают «исчезать» или дублироваться.

Рассмотрим подробно, как правильно реализовать связь между регистратором (движениями по себестоимости) и дополнительными документами расходов, не нарушая логику работы типового отчета.

Разбор типичных ошибок при создании связи

Проанализируем ситуацию: у нас есть основной запрос по регистру СебестоимостьТоваров, где поле Регистратор имеет составной тип. Мы хотим присоединить АвансовыйОтчет, который связан с производством не напрямую, а через ЗаказНаПроизводство. Часто разработчики пытаются написать условие связи следующим образом:


ВЫБОР 
    КОГДА ТИПЗНАЧЕНИЯ(ДД.Регистратор) = ТИП(Документ.ЭтапПроизводства2_2) 
    ТОГДА ДД.Регистратор = ЭтапПроизводства2_2.Ссылка 
КОНЕЦ

Выясним причину, почему это не эффективно и часто приводит к ошибкам:

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

Шаг 1. Предварительная подготовка данных во временной таблице

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

Разберем пример создания такой временной таблицы:


ВЫБРАТЬ
    АвансовыйОтчетПрочиеРасходы.Ссылка КАК АвансовыйОтчет,
    АвансовыйОтчетПрочиеРасходы.Ссылка.Подразделение КАК АвансовыйОтчетПодразделение,
    ВЫРАЗИТЬ(АвансовыйОтчетПрочиеРасходы.Ссылка.Комментарий КАК СТРОКА(1000)) КАК АвансовыйОтчетКомментарий,
    АвансовыйОтчетПрочиеРасходы.АналитикаРасходов КАК АналитикаРасходов
ПОМЕСТИТЬ ВТ_АвансовыеОтчеты
ИЗ
    Документ.АвансовыйОтчет.ПрочиеРасходы КАК АвансовыйОтчетПрочиеРасходы
ГДЕ
    АвансовыйОтчетПрочиеРасходы.Ссылка.Дата МЕЖДУ &НачалоПериода И &ОкончаниеПериода
    И АвансовыйОтчетПрочиеРасходы.Ссылка.Проведен
    И ТИПЗНАЧЕНИЯ(АвансовыйОтчетПрочиеРасходы.АналитикаРасходов) = ТИП(Документ.ЗаказНаПроизводство2_2)
;

В данном фрагменте мы сразу отсекаем лишние данные и работаем с аналитикой, которая указывает на заказ.

Шаг 2. Корректное соединение с основным запросом

Теперь рассмотрим, как привязать эту временную таблицу к основному источнику данных (регистру себестоимости). Важно понимать цепочку связей: ДД.Регистратор (если это ЭтапПроизводства2_2) имеет реквизит Распоряжение, который и является ссылкой на ЗаказНаПроизводство2_2. Именно по этому полю мы будем стыковаться с нашей ВТ_АвансовыеОтчеты.

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


ВЫБРАТЬ
    ДД.Регистратор,
    // ... другие поля типового запроса ...
    ЕСТЬNULL(ВТ_Авансы.АвансовыйОтчет, ЗНАЧЕНИЕ(Документ.АвансовыйОтчет.ПустаяСсылка)) КАК АвансовыйОтчет
ИЗ
    РегистрНакопления.СебестоимостьТоваров КАК ДД
    // Присоединяем этапы для получения распоряжения
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЭтапПроизводства2_2 КАК Этап
        ПО ДД.Регистратор = Этап.Ссылка
    // Присоединяем подготовленные авансы через распоряжение этапа
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_АвансовыеОтчеты КАК ВТ_Авансы
        ПО (ВЫРАЗИТЬ(Этап.Распоряжение КАК Документ.ЗаказНаПроизводство2_2)) = ВТ_Авансы.АналитикаРасходов

Шаг 3. Сохранение всех записей регистра (борьба с фильтрацией)

Если вам необходимо, чтобы отчет по-прежнему выводил все регистраторы, даже те, у которых нет авансового отчета, обратите пристальное внимание на секцию ГДЕ в самом конце запроса. Рассмотрим пример правильного написания условий:

Неправильно:
ГДЕ ВТ_Авансы.АвансовыйОтчет.Дата >= &НачалоПериода (строки с NULL в авансовом отчете исчезнут).

Правильно:
Все условия по фильтрации авансовых отчетов должны быть либо внутри запроса создания временной таблицы (как мы сделали выше), либо в самом условии связи ПО. Если же вы вынуждены оставить их в ГДЕ, используйте следующую конструкцию:


ГДЕ
    (ВТ_Авансы.АвансовыйОтчет ЕСТЬ NULL 
     ИЛИ (ВТ_Авансы.АвансовыйОтчет.Дата >= &НачалоПериода И НЕ ВТ_Авансы.АвансовыйОтчет.ПометкаУдаления))

Но помните: лучшая практика — передавать в соединение уже «чистую» таблицу ВТ_АвансовыеОтчеты, в которой остались только проведенные и актуальные документы. Это не только упрощает чтение запроса, но и значительно ускоряет выполнение за счет уменьшения количества соединяемых строк.

Рекомендации по оптимизации

При работе с 1С:ERP стоит помнить, что поле Регистратор — самое «тяжелое» для СУБД из-за огромного количества типов. Если ваша цель — связать затраты с этапами, попробуйте проанализировать поле Партия в регистре СебестоимостьТоваров. В производственных операциях Партия часто напрямую содержит ссылку на ЭтапПроизводства2_2. Связь через Партию может отработать быстрее, чем через Регистратор, так как состав типов в Партии значительно меньше.

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

← На главную