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

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

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

Проанализируем причину возникновения такой ситуации и рассмотрим несколько способов её решения.

Выясним причину появления пустой строки

Главная причина разворачивания данных в пустую строку заключается в разнице заполнения измерений или реквизитов в объединяемых регистрах. Например, если в первом регистре измерение ВидПродажи заполнено значением из перечисления, а во втором регистре при определенных операциях (например, при оплате списком) это поле остается незаполненным (содержит пустую ссылку, NULL или НЕОПРЕДЕЛЕНО), платформа не может сгруппировать эти записи в одну строку.

На уровне СУБД пустая ссылка одного типа данных и незаполненное значение или NULL другого типа приводят к образованию составного типа данных. Из-за этого СКД рассматривает их как совершенно разные группировочные значения.

Решение 1. Подстановка значения по умолчанию через выражение ВЫБОР

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

Рассмотрим пример запроса, в котором незаполненное значение измерения подменяется нужным значением перечисления:


ВЫБРАТЬ
    ПродажиПоСотрудникамОбороты.РозничнаяТочка КАК РозничнаяТочка,
    ВЫБОР
        КОГДА ПродажиПоСотрудникамОбороты.ВидПродажи ЕСТЬ NULL 
            ИЛИ ПродажиПоСотрудникамОбороты.ВидПродажи = ЗНАЧЕНИЕ(Перечисление.ВидыПродаж.ПустаяСсылка)
            ТОГДА ЗНАЧЕНИЕ(Перечисление.ВидыПродаж.Наличные)
        ИНАЧЕ ПродажиПоСотрудникамОбороты.ВидПродажи
    КОНЕЦ КАК ВидПродажи,
    ПродажиПоСотрудникамОбороты.СуммаОборот КАК СуммаОборот,
    ПродажиПоСотрудникамОбороты.Регистратор КАК Регистратор
ИЗ
    РегистрНакопления.ПродажиПоСотрудникам.Обороты(&НачалоПериода, &КонецПериода, Регистратор, ) КАК ПродажиПоСотрудникамОбороты

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

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

Решение 2. Использование объекта «Набор данных — Объединение»

Вместо объединения таблиц с помощью ключевого слова ОБЪЕДИНИТЬ внутри одного текста запроса можно вынести каждый регистр в самостоятельный Набор данных — Запрос.

  1. Создадим первый набор данных для первого регистра накопления.
  2. Создадим второй набор данных для второго регистра.
  3. Поместим оба набора внутрь родительского объекта Набор данных — Объединение на вкладке «Наборы данных».

В этом случае СКД выполнит каждый запрос отдельно и объединит их результаты по одинаковым именам полей. Это предотвращает проблемы со сведением неопределенных типов данных на уровне СУБД и дает возможность более гибко настраивать компоновку.

Решение 3. Явное приведение типов

Если из одного подзапроса поле передается как NULL, обязательно используйте явное приведение типов с помощью функции ВЫРАЗИТЬ() или пустую ссылку нужного типа:

ВЫРАЗИТЬ(NULL КАК Справочник.ВидыПродаж)

Или подстановку пустой ссылки перечисления:

ЗНАЧЕНИЕ(Перечисление.ВидыПродаж.ПустаяСсылка)

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

Рекомендации по оптимизации запросов СКД

При написании условий отбора и обработке полей учитывайте рекомендации по производительности:

  1. Не используйте обращения к реквизитам через точку в отборах. Избегайте конструкций вида ВидПродажи.Наименование = "Наличные". Обращение к реквизитам ссылочного типа через точку создаёт неявное левое соединение с таблицей справочника, что снижает скорость выполнения запроса. По возможности выполняйте сравнение непосредственно по ссылке: ВидПродажи = &СсылкаНаВидПродажи.
  2. Анализируйте периодичность виртуальных таблиц. Указание периодичности Регистратор в параметрах виртуальной таблицы оборотов разворачивает результат до конкретных документов. Из-за этого данные из разных регистров будут группироваться только на уровне общих группировок, но не на детальном уровне.
← На главную