Как в СКД вывести данные из двух регистров с разной детализацией без задвоения резервов

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

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

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

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

Анализ исходного запроса и причины ошибки

Посмотрим на типовой запрос, который приводит к размножению строк:


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

В результате такого соединения для одного товара с тремя партиями формируются три записи в выборке. Значение из поля Резерв дублируется во всех трех строках. Если для ресурса указана функция Сумма(Резерв), СКД суммирует резерв по каждой строке партии, что дает неверный результат. Если указать Максимум(Резерв), общий итог сойдется, но цифра резерва продолжит выводиться напротив каждой отдельной партии.

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

Способ 1. Раздельная настройка выбранных полей в группировках

Этот способ является наиболее простым и правильным с точки зрения архитектуры СКД. Он позволяет вывести колонку с резервом на уровне товара и полностью убрать ее со строк с партиями.

Разберем по шагам порядок настройки:

  1. Перейдем на вкладку Настройки схемы компоновки данных.
  2. В структуре отчета создадим иерархию группировок: группировка верхнего уровня Товар, внутри нее — подчиненная группировка Партия.
  3. Выделим корневой элемент структуры (или группировку Товар) и на вкладке Выбранные поля укажем: Остаток и Резерв.
  4. Выделим подчиненную группировку Партия, перейдем на ее вкладку Выбранные поля и отключим автонаследование полей (снимем флаг с элемента Автополе или удалим его).
  5. Вручную добавим в выбранные поля группировки Партия только поле Остаток.

В результате колонка Резерв будет заполняться только на уровне строки Товар, а на детальных строках партий останутся только их фактические остатки.

Способ 2. Настройка вычисления ресурсов по группировкам

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

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


Выбор 
    Когда ЗначениеЗаполнено(Партия) Тогда 0 
    Иначе Сумма(Резерв) 
Конец

Для корректной работы СКД выполним следующие действия:

  1. Откроем вкладку Ресурсы.
  2. Для поля Резерв укажем приведенное выше выражение.
  3. В колонке Рассчитывать по... отметим группировки: Товар, Склад и ОбщийИтог.

Обратите внимание: если добавить одно и то же поле в список ресурсов несколько раз без точного указания списка группировок в колонке Рассчитывать по..., платформа выдаст ошибку Повторяющееся поле итога. Каждая строка ресурса должна иметь строго определенный и непересекающийся список группировок расчета.

Способ 3. Переход на объединение запросов (ОБЪЕДИНИТЬ ВСЕ)

Чтобы избежать денормализации данных и дублирования строк еще на этапе выполнения запроса к СУБД, заменим ЛЕВОЕ СОЕДИНЕНИЕ на объединение выборок.

Рассмотрим структуру такого запроса:


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

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

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

Преимущества такого подхода:

  1. Строки с резервом не размножаются на количество партий.
  2. На вкладке Ресурсы для обоих полей (Остаток и Резерв) можно использовать стандартное агрегатное выражение Сумма(...).
  3. На уровне группировки Товар резервы и остатки суммируются корректно, а внутри строк с заполненными партиями колонка резерва естественным образом содержит ноль.

Способ 4. Использование связей наборов данных

Если логика отчета требует разделения данных, создадим два независимых набора данных (НаборДанных1 — по остаткам, НаборДанных2 — по резервам).

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

  1. На вкладке Связи наборов данных укажем источник (набор с остатками) и приемник (набор с резервами).
  2. Настроим условия связи по полям: Склад = Склад и Товар = Товар.
  3. В параметрах связи укажем передачу параметров по текущей группировке.
  4. Поле Резерв подключаем в выбранные поля группировки Товар. Для группировки Партия это поле не выбирается.

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

← На главную