Как в СКД правильно отобрать пустые значения (NULL) при связи наборов данных?

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

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

Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим практические способы решения этой задачи.

Почему не работает отбор по отсутствующим значениям в подчиненном наборе

Выясним причину такого поведения процессора компоновки данных. По умолчанию механизм связей между наборами данных СКД работает по аналогии с левым соединением (LEFT JOIN). Однако при наложении отбора на уровне отчета логика меняется:

  1. Оптимизация связей СКД. Когда на поле зависимого (правого) набора данных накладывается отбор на уровне всего отчета, платформа автоматически трансформирует тип соединения во внутреннее (INNER JOIN). Из-за этого строки основного набора, для которых во втором наборе данных нет записей, полностью исключаются из итоговой выборки.
  2. Контекст применения отборов. Фильтры по зависимым наборам накладываются на этапе выборки данных именно этого набора, а не после их объединения в памяти. Поскольку в зависимом наборе физически отсутствуют записи для пустых сопоставлений, условие отбора возвращает ложь, и результирующая таблица оказывается пустой.

Способ 1. Вынесение проверки наличия связанных данных в основной запрос

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

Посмотрим на пример формирования поля-признака с помощью конструкции ВЫБОР КОГДА ... СУЩЕСТВУЕТ:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура,
    ВЫБОР
        КОГДА СУЩЕСТВУЕТ
            (ВЫБРАТЬ
                1
            ИЗ
                РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены
            ГДЕ
                Цены.Номенклатура = Номенклатура.Ссылка)
        ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ЕстьЦена
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    НЕ Номенклатура.ЭтоГруппа

В этом случае отбор накладывается на поле ЕстьЦена, которое принадлежит основному набору. Соединения не трансформируются во внутренние, а фильтрация отрабатывает корректно при установке значения Ложь.

Способ 2. Использование вычисляемых полей и фильтрация на уровне группировок

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

  1. Перейдем на вкладку Вычисляемые поля и добавим новое поле, например ПолеЗаполнено.
  2. В колонке Выражение укажем формулу проверки: ВЫБОР КОГДА ПолеСвязанногоНабора ЕСТЬ NULL ТОГДА ЛОЖЬ ИНАЧЕ ИСТИНА КОНЕЦ
  3. Перейдем на вкладку Настройки. Важно: не накладывайте отбор в общих отборах отчета (на самом верхнем уровне Отчет).
  4. Откроем настройки конкретной группировки строк (или группировки Детальные записи) и добавим отбор по полю ПолеЗаполнено Равно Ложь именно на уровень этой группировки.

При таком подходе СКД не преобразует глобальное левое соединение наборов во внутреннее соединение на этапе инициализации выборки, и фильтр отработает по сформированным в группировке записям.

Способ 3. Проверка флага отключения скрытия строк NULL в группировках

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

  1. Выберем группировку в дереве структуры отчета на вкладке Настройки.
  2. В окне свойств выбранной группировки найдем параметр Игнорировать значения NULL (или Авто поле NULL в зависимости от версии схемы).
  3. Снимем соответствующий флаг, чтобы предотвратить скрытие строк главного набора данных, для которых зависимые поля равны NULL.
  4. Для ключевых полей родительского набора на вкладке Наборы данных в колонке Роль установим флаг Обязательное, что гарантирует сохранение записей основного источника.

Способ 4. Использование родительского набора «Объединение»

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

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

← На главную