При разработке отчетов в системе компоновки данных (СКД) часто возникает задача соединить несколько наборов данных и отобрать те строки главного набора, для которых во втором наборе нет соответствий (например, документы без присоединенных файлов или номенклатура без установленных цен). Однако стандартная установка отбора по типу Не заполнено или Равно NULL для поля зависимого набора данных приводит к тому, что в результат отчета не попадает вообще ничего.
Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим практические способы решения этой задачи.
Выясним причину такого поведения процессора компоновки данных. По умолчанию механизм связей между наборами данных СКД работает по аналогии с левым соединением (LEFT JOIN). Однако при наложении отбора на уровне отчета логика меняется:
INNER JOIN). Из-за этого строки основного набора, для которых во втором наборе данных нет записей, полностью исключаются из итоговой выборки.Рассмотрим наиболее надежный и производительный способ. Вместо создания нескольких отдельных наборов данных и попыток связать их на вкладке Связи наборов данных, перенесем проверку наличия данных непосредственно в текст запроса основного набора.
Посмотрим на пример формирования поля-признака с помощью конструкции ВЫБОР КОГДА ... СУЩЕСТВУЕТ:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ВЫБОР
КОГДА СУЩЕСТВУЕТ
(ВЫБРАТЬ
1
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены
ГДЕ
Цены.Номенклатура = Номенклатура.Ссылка)
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК ЕстьЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
НЕ Номенклатура.ЭтоГруппа
В этом случае отбор накладывается на поле ЕстьЦена, которое принадлежит основному набору. Соединения не трансформируются во внутренние, а фильтрация отрабатывает корректно при установке значения Ложь.
Проанализируем вариант, когда структуру наборов данных менять нежелательно. Если связь наборов сохраняется, можно добавить вычисляемое поле, но накладывать отбор необходимо строго в определенных местах схемы компоновки.
ПолеЗаполнено.
ВЫБОР КОГДА ПолеСвязанногоНабора ЕСТЬ NULL ТОГДА ЛОЖЬ ИНАЧЕ ИСТИНА КОНЕЦ
Отчет).Детальные записи) и добавим отбор по полю ПолеЗаполнено Равно Ложь именно на уровень этой группировки.При таком подходе СКД не преобразует глобальное левое соединение наборов во внутреннее соединение на этапе инициализации выборки, и фильтр отработает по сформированным в группировке записям.
Разберем ситуацию, когда данные исчезают при выводе подчиненного набора в структуру группировок. По умолчанию платформа может оптимизировать и схлопывать пустые значения.
NULL.Если требуется объединить разнородные данные (например, данные из базы и внешней таблицы), создадим набор данных типа Объединение, внутрь которого поместим основной и подчиненный наборы данных.
В отличие от механизма связей через параметры, набор-объединение сохраняет строки главного источника независимо от условий фильтрации, так как компоновщик обрабатывает каждую ветку объединения параллельно.