Как объединить данные из «Этапа производства 2.2» и «Заказа клиента» в одном запросе без дублирования строк?

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

В процессе разработки отчетов в 1С:ERP или Комплексной автоматизации часто возникает необходимость сопоставить данные о фактически выпущенной продукции (из документов ЭтапПроизводства2_2) и плановые показатели из распоряжений (документов ЗаказКлиента). Основная сложность заключается в том, что прямые соединения табличных частей часто приводят к "размножению" строк и некорректным итогам, особенно если в заказе одна и та же номенклатура указана несколькими строками с разными ценами.

В этой статье мы подробно разберем, как правильно выстроить структуру запроса, используя временные таблицы и объединения, чтобы получить точные данные в разрезе номенклатуры, этапов и цен.

Анализ проблемы: почему данные дублируются

Проанализируем типичную ситуацию: в Заказе клиента есть две строки с одной и той же номенклатурой, но разными ценами или характеристиками. В документе Этап производства 2.2 зафиксирован выпуск этой же номенклатуры одной строкой. Если мы выполним ЛЕВОЕ СОЕДИНЕНИЕ этапа с заказом по полю Номенклатура, система создаст две записи для одной строки выпуска. В результате при суммировании количество выпущенной продукции удвоится.

Чтобы избежать этой ошибки, мы применим стратегию разделения данных по разным временным таблицам с последующим использованием оператора ОБЪЕДИНИТЬ ВСЕ и финальной группировкой.

Шаг 1. Отбор исходных документов во временную таблицу

Рассмотрим первый этап оптимизации. Вместо того чтобы сразу работать со всеми данными, сначала выберем только нужные ссылки на документы и их основные связи. Это позволит сократить объем обрабатываемых данных и повысить производительность запроса.


ВЫБРАТЬ
    ЭтапПроизводства2_2.Распоряжение.ДокументОснование.Ссылка КАК ЗаказКлиента,
    ЭтапПроизводства2_2.Ссылка КАК ЭтапПроизводство
ПОМЕСТИТЬ ВТОтобранныеДанные
ИЗ
    Документ.ЭтапПроизводства2_2 КАК ЭтапПроизводства2_2
ГДЕ
    ЭтапПроизводства2_2.Ссылка В(&Ссылка)
    И ЭтапПроизводства2_2.Проведен;

Важный момент: использование фильтра Проведен является базовым, однако для производственных документов ERP рекомендуется дополнительно проверять статус этапа (например, Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЭтаповПроизводства2_2.Завершен)), чтобы быть уверенными в актуальности данных о выпуске.

Шаг 2. Получение данных из табличной части выпуска

Теперь выберем данные о выпущенной номенклатуре. Мы соединяем нашу временную таблицу отобранных ссылок с табличной частью ВыходныеИзделия. Обратите внимание на использование функции ЕСТЬNULL для числовых полей.


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

Шаг 3. Получение данных из Заказа клиента

На этом этапе мы выбираем плановые данные из заказа. Чтобы запрос работал корректно, мы ограничиваем выборку только теми заказами, которые фигурируют в наших отобранных этапах. Выясним причину использования вложенного запроса в условии ГДЕ: это позволяет избежать лишних соединений на ранних этапах.


ВЫБРАТЬ
    ЗаказКлиентаТовары.Ссылка КАК ЗаказКлиента,
    ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
    ЗаказКлиентаТовары.Количество КАК КоличествоИзЗаказа,
    ЗаказКлиентаТовары.Цена КАК ЦенаИзЗаказа
ПОМЕСТИТЬ втТаблицаТоваровИзЗаказа
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ГДЕ
    ЗаказКлиентаТовары.Ссылка В (ВЫБРАТЬ ВТОтобранныеДанные.ЗаказКлиента ИЗ ВТОтобранныеДанные КАК ВТОтобранныеДанные);

Шаг 4. Объединение и финальная группировка

Рассмотрим самый ответственный момент: сборку итоговой таблицы. Мы не соединяем таблицы выпуска и заказа "в бок", а ставим их друг под друга через ОБЪЕДИНИТЬ ВСЕ. Это гарантирует, что ни одна строка не будет продублирована или потеряна. Для сопоставления данных в одну строку мы используем последующую группировку по ключевым полям: ЭтапПроизводство, ЗаказКлиента и Номенклатура.


ВЫБРАТЬ
    втИтоговые.ЭтапПроизводство КАК ЭтапПроизводство,
    втИтоговые.ЗаказКлиента КАК ЗаказКлиента,
    втИтоговые.Номенклатура КАК Номенклатура,
    СУММА(втИтоговые.Количество) КАК КоличествоВыпуск,
    СУММА(втИтоговые.КоличествоИзЗаказа) КАК КоличествоЗаказ,
    МАКСИМУМ(втИтоговые.ЦенаИзЗаказа) КАК Цена
ИЗ
    (ВЫБРАТЬ
        втТаблицаВыходныхИзделий.ЭтапПроизводство,
        втТаблицаВыходныхИзделий.ЗаказКлиента,
        втТаблицаВыходныхИзделий.Номенклатура,
        втТаблицаВыходныхИзделий.Количество КАК Количество,
        0 КАК КоличествоИзЗаказа,
        0 КАК ЦенаИзЗаказа
    ИЗ
        втТаблицаВыходныхИзделий КАК втТаблицаВыходныхИзделий
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        NULL,
        втТаблицаТоваровИзЗаказа.ЗаказКлиента,
        втТаблицаТоваровИзЗаказа.Номенклатура,
        0,
        втТаблицаТоваровИзЗаказа.КоличествоИзЗаказа,
        втТаблицаТоваровИзЗаказа.ЦенаИзЗаказа
    ИЗ
        втТаблицаТоваровИзЗаказа КАК втТаблицаТоваровИзЗаказа) КАК втИтоговые

СГРУППИРОВАТЬ ПО
    втИтоговые.ЭтапПроизводство,
    втИтоговые.ЗаказКлиента,
    втИтоговые.Номенклатура

Дополнительные рекомендации для точности данных

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

  1. Использование поля КлючСтроки: В ERP 2.4/2.5 для связи строк заказа с производственными документами используется идентификатор КлючСтроки. Если ваша задача требует точности до конкретной строки заказа, обязательно включайте это поле в условия связи и группировки.
  2. Связь через Назначение: Если на предприятии используется обособленный учет, то поле Назначение в табличных частях будет содержать ссылку на конкретный заказ. Это самый надежный способ связать выпуск и потребность.
  3. Индексация: При работе с большим количеством этапов (более 1000) обязательно добавляйте ИНДЕКСИРОВАТЬ ПО для временных таблиц по полям ЗаказКлиента и Номенклатура. Это критически важно для скорости выполнения запроса.
  4. Регистры накопления: Посмотрим на альтернативный подход. Запрос к табличным частям документов считается "тяжелым". Для получения информации о выпуске лучше использовать виртуальные таблицы регистра накопления ВыпускПродукции. Данные в регистрах уже содержат готовую аналитику по заказам и распоряжениям, что упрощает структуру запроса.

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

← На главную