При разработке отчетов в Системе компоновки данных (СКД) часто возникает ситуация, когда при соединении двух наборов данных ожидается сохранение логики ЛЕВОЕ СОЕДИНЕНИЕ, но после установки отбора в настройках отчета результат неожиданно обрезается, как при ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Давайте разберемся, почему это происходит и как заставить отчет работать корректно.
Когда мы накладываем отбор на поле правого набора данных в стандартном разделе «Отбор» настроек отчета, СКД автоматически переносит это условие в итоговый блок WHERE SQL-запроса. Если в результате левого соединения запись из правого набора отсутствует (содержит NULL), то условие WHERE (например, ПолеПравогоНабора = Значение) отсекает такую строку, так как NULL не проходит проверку. В итоге мы теряем все записи левого набора, для которых не нашлось пары в правом, и соединение де-факто становится внутренним.
Самый правильный способ сохранить логику левого соединения — не использовать общий отбор, а перенести условие на уровень связей. Рассмотрим этот метод подробнее:
Когда условие находится в Условие связи, оно попадает в секцию ON SQL-запроса. Это позволяет системе отфильтровать записи правого набора еще на этапе выполнения соединения, сохранив все записи из левого набора, даже если в правом наборе данных соответствия не найдено.
Если правый набор данных представляет собой запрос к ВиртуальнаяТаблица (например, остатки или обороты), наиболее эффективным решением будет передача параметров напрямую в эту таблицу. Рассмотрим шаги реализации:
{ГДЕ ПолеОтбора = &Параметр}.Ограничение доступности, если вы хотите, чтобы он заполнялся только программно или через параметры связи.Это решение не только корректно сохраняет тип соединения, но и значительно повышает производительность, так как база данных выполнит фильтрацию данных на уровне СУБД, еще до передачи результатов в СКД.
Если вы не хотите менять структуру запроса или связей, можно попробовать изменить область действия отбора. Попробуем наложить его не на весь отчет, а на конкретную группировку:
В некоторых случаях СКД применяет отбор на уровне группировки уже после процесса соединения, что позволяет «обмануть» систему и оставить записи из левого набора в итоговой таблице.
Если задача становится слишком сложной для встроенных механизмов связей СКД, лучше всего отказаться от использования связей наборов данных в пользу классического ОБЪЕДИНИТЬ ВСЕ или соединения внутри одного запроса. Рассмотрим пример логики:
ВЫБРАТЬ
ТаблицаА.Поле1,
ТаблицаБ.Поле2
ИЗ
ТаблицаА КАК ТаблицаА
ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаБ КАК ТаблицаБ
ПО ТаблицаА.Ключ = ТаблицаБ.Ключ
И (ТаблицаБ.ПолеОтбора = &Параметр)
Такой подход дает полный контроль над выполнением запроса. Вы четко видите, где находится ваше условие — в ON или WHERE, и можете быть уверены в предсказуемости результата.
Чтобы раз и навсегда разобраться в поведении вашего отчета, обязательно используйте инструмент Консоль системы компоновки данных. Анализируя текст итогового запроса, который генерирует СКД, вы сможете увидеть, в какую именно часть SQL-кода попадает ваше условие. Если вы видите, что оно добавлено в блок WHERE — значит, ваша текущая настройка неизбежно приведет к превращению левого соединения во внутреннее. Исправляйте это, перенося условие в параметры связи или параметры виртуальных таблиц.