Почему в СКД левое соединение наборов данных превращается во внутреннее при установке отбора?

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

При разработке отчетов в Системе компоновки данных (СКД) часто возникает ситуация, когда при соединении двух наборов данных ожидается сохранение логики ЛЕВОЕ СОЕДИНЕНИЕ, но после установки отбора в настройках отчета результат неожиданно обрезается, как при ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Давайте разберемся, почему это происходит и как заставить отчет работать корректно.

Суть проблемы

Когда мы накладываем отбор на поле правого набора данных в стандартном разделе «Отбор» настроек отчета, СКД автоматически переносит это условие в итоговый блок WHERE SQL-запроса. Если в результате левого соединения запись из правого набора отсутствует (содержит NULL), то условие WHERE (например, ПолеПравогоНабора = Значение) отсекает такую строку, так как NULL не проходит проверку. В итоге мы теряем все записи левого набора, для которых не нашлось пары в правом, и соединение де-факто становится внутренним.

Способ 1: Перенос условия в параметры связи

Самый правильный способ сохранить логику левого соединения — не использовать общий отбор, а перенести условие на уровень связей. Рассмотрим этот метод подробнее:

  1. Перейдите на вкладку Связи наборов данных в схеме компоновки.
  2. Найдите нужную связь между наборами.
  3. В колонке Условие связи пропишите необходимое условие.

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

Способ 2: Использование параметров виртуальных таблиц

Если правый набор данных представляет собой запрос к ВиртуальнаяТаблица (например, остатки или обороты), наиболее эффективным решением будет передача параметров напрямую в эту таблицу. Рассмотрим шаги реализации:

  1. В запросе правого набора добавьте параметр в параметры виртуальной таблицы, например: {ГДЕ ПолеОтбора = &Параметр}.
  2. Перейдите на вкладку Параметры в СКД.
  3. Установите для этого параметра свойство Ограничение доступности, если вы хотите, чтобы он заполнялся только программно или через параметры связи.

Это решение не только корректно сохраняет тип соединения, но и значительно повышает производительность, так как база данных выполнит фильтрацию данных на уровне СУБД, еще до передачи результатов в СКД.

Способ 3: Применение отбора к группировкам

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

  1. В настройках отчета выберите нужную Группировку.
  2. Перейдите в закладку Отбор этой группировки.
  3. Установите отбор там.

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

Способ 4: Объединение наборов в одном запросе

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


ВЫБРАТЬ
    ТаблицаА.Поле1,
    ТаблицаБ.Поле2
ИЗ
    ТаблицаА КАК ТаблицаА
    ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаБ КАК ТаблицаБ
    ПО ТаблицаА.Ключ = ТаблицаБ.Ключ
        И (ТаблицаБ.ПолеОтбора = &Параметр)

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

Рекомендации по отладке

Чтобы раз и навсегда разобраться в поведении вашего отчета, обязательно используйте инструмент Консоль системы компоновки данных. Анализируя текст итогового запроса, который генерирует СКД, вы сможете увидеть, в какую именно часть SQL-кода попадает ваше условие. Если вы видите, что оно добавлено в блок WHERE — значит, ваша текущая настройка неизбежно приведет к превращению левого соединения во внутреннее. Исправляйте это, перенося условие в параметры связи или параметры виртуальных таблиц.

← На главную