Как объединить данные о выпуске полуфабрикатов и готовой продукции из разных регистров в одном отчете 1С?

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

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

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

Анализ проблемы: ОБЪЕДИНИТЬ или СОЕДИНИТЬ?

Первоначальная попытка использовать оператор ОБЪЕДИНИТЬ ВСЕ часто приводит к тому, что данные просто «склеиваются» в одну колонку по вертикали. Чтобы получить данные в разных колонках одной строки (например, КолПФ и КолПродукции в одной строке), необходимо использовать левое или полное соединение.

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

Решение 1: Использование временных таблиц и группировок

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

Рассмотрим пример кода, где мы сначала собираем данные о полуфабрикатах, затем о продукции, и только в конце объединяем их:


// Шаг 1: Получаем данные о производстве полуфабрикатов
ВЫБРАТЬ
    МойРН.Бригада КАК Бригада,
    МойРН.КонечнаяПродукция КАК КонечнаяПродукция,
    МойРН.Полуфабрикат КАК Полуфабрикат,
    СУММА(МойРН.КоличествоПФ) КАК КоличествоПФ
ПОМЕСТИТЬ ВТ_Полуфабрикаты
ИЗ
    РегистрНакопления.МойРН.Обороты(&НачалоПериода, &КонецПериода, , ) КАК МойРН
СГРУППИРОВАТЬ ПО
    МойРН.Бригада,
    МойРН.КонечнаяПродукция,
    МойРН.Полуфабрикат;

// Шаг 2: Получаем данные о выпуске готовой продукции
ВЫБРАТЬ
    МойРН1.КонечнаяПродукция КАК КонечнаяПродукция,
    СУММА(МойРН1.КолКонечнойПродукции) КАК КоличествоГотовойПродукции
ПОМЕСТИТЬ ВТ_Продукция
ИЗ
    РегистрНакопления.МойРН1.Обороты(&НачалоПериода, &КонецПериода, , ) КАК МойРН1
СГРУППИРОВАТЬ ПО
    МойРН1.КонечнаяПродукция;

// Шаг 3: Соединяем данные
ВЫБРАТЬ
    ЕСТЬNULL(ВТ_Полуфабрикаты.Бригада, "Не определена") КАК Бригада,
    ЕСТЬNULL(ВТ_Полуфабрикаты.Полуфабрикат, "Не указан") КАК Полуфабрикат,
    ЕСТЬNULL(ВТ_Полуфабрикаты.КоличествоПФ, 0) КАК КоличествоПФ,
    ЕСТЬNULL(ВТ_Полуфабрикаты.КонечнаяПродукция, ВТ_Продукция.КонечнаяПродукция) КАК Изделие,
    ЕСТЬNULL(ВТ_Продукция.КоличествоГотовойПродукции, 0) КАК КоличествоГотовойПродукции
ИЗ
    ВТ_Полуфабрикаты КАК ВТ_Полуфабрикаты
        ПОЛНОЕ СОЕДИНЕНИЕ ВТ_Продукция КАК ВТ_Продукция
        ПО ВТ_Полуфабрикаты.КонечнаяПродукция = ВТ_Продукция.КонечнаяПродукция

Обратим внимание на использование функции ЕСТЬNULL. Это критически важно при ПОЛНОМ СОЕДИНЕНИИ, так как если данных по полуфабрикату нет, но есть выпуск продукции, мы всё равно увидим строку в отчете.

Решение 2: Система компоновки данных (СКД)

Выясним, почему СКД часто является более предпочтительным вариантом для таких задач. Вместо написания одного огромного запроса с соединениями, мы можем создать два независимых Набора данных - запрос.

  1. Создаем НаборДанных1, который выбирает данные из первого регистра (Бригада, ПФ, Продукция, КоличествоПФ).
  2. Создаем НаборДанных2, который выбирает данные из второго регистра (Продукция, КоличествоПродукции).
  3. На закладке "Связи наборов данных" указываем связь по полю КонечнаяПродукция.

Преимущество этого метода: СКД автоматически выполнит «левое соединение» на уровне вывода результата. Если одно конечное изделие встречается в НабореДанных1 несколько раз (для разных ПФ), СКД не будет суммировать количество из НабораДанных2 повторно для каждой строки, если правильно настроить ресурсы и группировки. Это избавляет разработчика от необходимости вручную вычислять коэффициенты распределения.

Важные нюансы и рекомендации

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

  1. Виртуальные таблицы: Всегда используйте виртуальную таблицу .Обороты() вместо физической таблицы регистра накопления. Это значительно повышает производительность запроса, так как система обращается к уже рассчитанным итогам, а не пересчитывает все записи в базе данных.
  2. Распределение выпуска по бригадам: Если во втором регистре (выпуск продукции) нет аналитики Бригада, а одна и та же продукция может производиться разными бригадами, прямое соединение покажет общий итог выпуска для каждой бригады. В этом случае полезно рассмотреть возможность связи через Регистратор (документ-основание), если оба регистра двигаются одним документом.
  3. Характеристики: Если ваша номенклатура использует характеристики, обязательно включайте поле Характеристика в условия связи (JOIN). Игнорирование характеристик приведет к «схлопыванию» данных по разным видам одного и того же товара.

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

← На главную