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

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

При разработке сложных отчетов в системе компоновки данных (СКД) часто возникает задача объединения нескольких наборов данных. Типичный сценарий: один набор данных содержит детальную информацию по продажам с аналитикой по номенклатуре, а второй набор — общие плановые показатели или данные по взаиморасчетам, где номенклатура отсутствует. Рассмотрим ситуацию, когда при наложении отбора по полю, существующему только в одном наборе, записи из второго набора бесследно исчезают. Разберем, почему это происходит и как правильно настроить схему, чтобы отчет работал корректно.

Почему пропадают данные при объединении наборов?

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

Проблема возникает в тот момент, когда пользователь накладывает стандартный отбор. Например, условие Номенклатура Равно "Кирпич". Для первого набора это условие отрабатывает ожидаемо. Однако для записей второго набора, где в поле Номенклатура стоит NULL, условие NULL = "Кирпич" всегда будет ложным. В результате система отсекает все строки второго набора, и пользователь видит неполную картину данных.

Решение через расширение языка запросов {ГДЕ ...}

Самый эффективный способ решить проблему — использовать возможности расширения языка запросов СКД. Вместо того чтобы полагаться на автоматическую генерацию условий компоновщиком, мы можем явно указать, в каком именно наборе должен применяться отбор. Рассмотрим этот метод пошагово.

Для этого в наборе данных, содержащем нужное поле, перейдем на закладку Компоновка данных в конструкторе запроса и в секции «Условия» пропишем конструкцию в фигурных скобках. Это позволит сделать поле доступным для отбора, но ограничит его область действия только текущим запросом.

Пример кода в тексте запроса для набора, где поле Контрагент присутствует:


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

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

Использование псевдонимов и представлений для удобства пользователя

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

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

Таким образом, в пользовательском режиме человек будет видеть одно поле «Номенклатура» в настройках отбора, но логика СКД применит фильтр только к нужному фрагменту объединения.

Нюансы работы с наборами данных «Объект»

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

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

Явное приведение типов (CAST)

Посмотрим на еще один важный момент. При объединении наборов, где в одном из них поле отсутствует, СКД может ошибиться с определением типа этого виртуального поля. Чтобы отборы по иерархии или ссылочные сравнения работали корректно, рекомендуется во втором наборе (где поля нет) явно создать «пустышку» с нужным типом.

Пример создания типизированного пустого поля в запросе:


ВЫБРАТЬ
    ВЫРАЗИТЬ(NULL КАК Справочник.Контрагенты) КАК Контрагент,
    0 КАК Сумма

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

Заключение

Мы рассмотрели основной механизм решения проблемы «исчезающих записей» при объединении наборов. Главным инструментом программиста здесь выступает расширение запроса {ГДЕ ...}, которое позволяет локализовать условия фильтрации. Правильное комбинирование этого метода с настройкой представлений и ролей полей позволяет создавать гибкие и надежные отчеты, которые ведут себя предсказуемо для пользователя даже при сложной структуре источников данных.

← На главную