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