Почему не отображаются подразделения при соединении регистров склада и производства в СКД

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке сложных отчетов в системе 1С программисты часто сталкиваются с необходимостью объединить данные из нескольких регистров накопления. Типичный пример — сопоставление остатков товаров на складах и материалов, переданных в производство (незавершенное производство — НЗП). Однако при попытке связать эти таблицы «в лоб» через левое соединение разработчики получают пустые строки вместо названий подразделений или сталкиваются с критическими ошибками компоновки данных.

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

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

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


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

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

// Соединение таблиц
ВЫБРАТЬ
    ВтСклад.Номенклатура,
    ВтСклад.КоличествоКонечныйОстаток КАК ОстатокСклад,
    ВтНЗП.КоличествоКонечныйОстаток КАК ОстатокНЗП,
    ВтНЗП.Подразделение
ИЗ
    ВтСклад КАК ВтСклад
    ЛЕВОЕ СОЕДИНЕНИЕ ВтНЗП КАК ВтНЗП 
        ПО ВтСклад.Номенклатура = ВтНЗП.Затрата 
        И ВтСклад.ПериодДень = ВтНЗП.ПериодДень

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

Причина №1. Ошибка логики левого соединения по периоду (ПериодДень)

Главная архитектурная ошибка в данном запросе кроется в условии связи: И ВтСклад.ПериодДень = ВтНЗП.ПериодДень.

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

  1. 5-го числа товар «Сельдь» поступил на склад. В таблице ВтСклад появляется строка с периодом 05.11.2023. В производстве по этому товару движений не было.
  2. 10-го числа этот же товар «Сельдь» был передан в производство в подразделение «Кухня». В таблице ВтНЗП появляется строка с периодом 10.11.2023. На складе в этот день движений по селедке не было.

Когда СУБД выполняет левое соединение по условию равенства дат, строка склада за 5-е число пытается сопоставиться со строками производства за 5-е число. Поскольку в производстве за 5-е число записей нет, СУБД возвращает для поля Подразделение значение NULL (которое в отчете выводится как пустая строка).

Аналогично, если мы попытаемся сделать соединение полным, строки за разные даты просто не пересекутся. Нам выведутся отдельные строки для склада за 5-е число (без подразделения) и отдельные строки для производства за 10-е число. Стыковки остатков по дням не произойдет.

Причина №2. Ошибки при попытке сделать подразделение ресурсом СКД

Пытаясь обойти проблему пустых значений, разработчики часто пробуют назначить нечисловое поле Подразделение ресурсом на вкладке «Ресурсы» в схеме компоновки данных. Это приводит к двум популярным ошибкам.

Ошибка компоновки макета (ограничения группировок)

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

«Не допускается группировка по полю-ресурсу в колонках таблицы или точках диаграммы...»

Она означает, что в настройках структуры отчета (на вкладке «Настройки») поле Подразделение было ошибочно оставлено в роли группировки колонок или строк. Ресурсы в СКД предназначены исключительно для вычисления итоговых значений в точках пересечения группировок, их нельзя использовать в качестве самих осей группировки.

Синтаксическая ошибка в выражении ресурса

Для нечисловых полей (таких как справочники, перечисления или строки) нельзя использовать агрегатную функцию по умолчанию — СУММА. Попытка просуммировать ссылки на подразделения вызовет синтаксическую ошибку при выполнении запроса.

Если вам действительно необходимо сделать измерение (например, подразделение) ресурсом, чтобы оно агрегировалось на уровне вышестоящих группировок, в поле выражения на вкладке «Ресурсы» следует явно прописать функции выбора значений:

Это позволит СКД корректно выводить строковое или ссылочное значение на уровне итогов, если оно уникально в рамках группировки.

---

Правильные варианты решения проблемы

Рассмотрим два профессиональных подхода к проектированию таких отчетов в 1С, исключающих дублирование остатков и гарантирующих вывод всех необходимых аналитик.

Вариант А. Использование объединения («ОБЪЕДИНИТЬ ВСЕ») вместо соединений

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

Разберем детально этот запрос:


ВЫБРАТЬ
    Склад.Номенклатура КАК Номенклатура,
    Склад.Склад КАК Склад,
    ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка) КАК Подразделение,
    Склад.КоличествоКонечныйОстаток КАК ОстатокСклад,
    0 КАК ОстатокПроизводство
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Склад

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Производство.Затрата,
    ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка),
    Производство.Подразделение,
    0,
    Производство.КоличествоКонечныйОстаток
ИЗ
    РегистрНакопления.МатериалыВПроизводстве.Остатки(&Период, ) КАК Производство

Почему это работает правильно:

  1. Каждый регистр выбирает только свои данные. Нет никакого риска «размножения» складских остатков, если у одного товара в производстве окажется несколько разных подразделений.
  2. В ветке склада мы подставляем пустую ссылку подразделения, а в ветке производства — пустую ссылку склада.
  3. В СКД мы настраиваем группировку по полю Номенклатура. Система автоматически схлопнет строки. В детальных записях мы увидим отдельно складские остатки (с заполненным складом) и производственные (с заполненным подразделением).

Вариант Б. Связи наборов данных в СКД

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

Выполним настройку по шагам:

Шаг 1. Создание наборов данных

В схеме компоновки данных создаем два независимых набора данных - запрос:

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

Шаг 2. Настройка связи наборов данных

Переходим на вкладку «Связи наборов данных» и добавляем новую строку:

При таком подходе СКД гарантирует корректный расчет итоговых показателей по складу и производству, исключая дублирование данных и пустые строки при выводе группировок.

Резюме

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

← На главную