Рассмотрим достаточно частую и интересную задачу, с которой сталкиваются разработчики при работе с Системой Компоновки Данных (СКД) в 1С. Проанализируем ситуацию: у нас есть набор данных-запрос, внутри которого используется оператор объединения запросов. Нам необходимо сделать так, чтобы при установке пользовательского отбора в настройках СКД, этот отбор наложился только на один запрос из объединения, а для второго запроса — был проигнорирован.
Разберем конкретный пример: пользователь устанавливает отбор по полям Организация, Клиент и Менеджер. Мы хотим, чтобы в первой части объединения отработали все три фильтра, а во второй части — только Организация и Менеджер, полностью проигнорировав отбор по клиенту, даже если поле с таким именем присутствует во втором запросе. Посмотрим, почему стандартное поведение системы вызывает сложности и как мы вместе можем решить эту задачу несколькими способами.
Выясним причину такого поведения. Когда в свойствах набора данных установлена галочка Автозаполнение, СКД анализирует текст запроса и самостоятельно определяет, куда подставить условия отбора. При использовании оператора объединения, система пытается транслировать пользовательские фильтры на все выборки, входящие в запрос. Если во второй части запроса поле отсутствует или заменено на NULL, в релизах платформы начиная с 8.3.14 СКД добавит некорректное условие сравнения с NULL, из-за чего процессор компоновки вернет пустой или неверный результат.
Давайте подробно рассмотрим три эффективных способа обойти это ограничение.
Это самый правильный и контролируемый метод, основанный на расширении языка запросов СКД. Разберем по шагам, как его применить.
Посмотрим на пример того, как должен выглядеть синтаксис в тексте запроса:
ВЫБРАТЬ
Таблица1.Организация КАК Организация,
Таблица1.Клиент КАК Клиент,
Таблица1.Менеджер КАК Менеджер,
Таблица1.Сумма КАК Сумма
ИЗ
РегистрНакопления.Продажи КАК Таблица1
{ГДЕ
Таблица1.Организация.* КАК Организация,
Таблица1.Клиент.* КАК Клиент,
Таблица1.Менеджер.* КАК Менеджер}
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Таблица2.Организация,
Таблица2.Клиент,
Таблица2.Менеджер,
Таблица2.Сумма
ИЗ
РегистрНакопления.Возвраты КАК Таблица2
{ГДЕ
Таблица2.Организация.* КАК Организация,
Таблица2.Менеджер.* КАК Менеджер}
В этом примере мы явно указали СКД, что отбор по полю Клиент может применяться только в первой части запроса. Во второй части мы секцию для клиента намеренно опустили. Обратите внимание на необходимость ручного заполнения полей на закладке "Поля", так как мы отключили автозаполнение.
Рассмотрим альтернативный путь. Вместо того чтобы писать оператор объединения прямо в тексте одного набора данных, архитектура СКД позволяет решить эту задачу на более высоком уровне. Этот способ отлично подходит, если запросы логически независимы и вы хотите сохранить включенным Автозаполнение.
НаборДанныхОбъединение.НаборДанныхЗапрос (назовем их, например, "ЗапросПродажи" и "ЗапросВозвраты").Клиент вообще не включаем в выборку второго запроса).Как это работает? СКД самостоятельно объединит результаты этих двух наборов на уровне процессора компоновки. При этом отборы будут накладываться изолированно: если пользователь установит фильтр по клиенту, система применит его только к первому набору данных, так как во втором наборе такого поля просто нет в списке доступных полей. Это очень элегантное архитектурное решение.
Проанализируем еще один обходной маневр, который обсуждается разработчиками. Он менее надежен, но в некоторых случаях может быть полезен, если вы не хотите разбивать запрос или отключать автозаполнение.
Суть заключается в том, чтобы во второй таблице задать полю другой псевдоним.
ВЫБРАТЬ
Организация,
Клиент,
Менеджер
ИЗ
Таблица1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Организация,
Клиент КАК НеКлиент,
Менеджер
ИЗ
Таблица2
При включенном автозаполнении СКД добавит новое поле НеКлиент в список полей набора данных. Далее нам необходимо зайти на вкладку "Поля" и принудительно установить ограничения: для поля НеКлиент снимаем галочки в колонке "Ограничение поля" и "Ограничение условия" (запрещаем использовать его в отборах). Таким образом, основной отбор по полю Клиент не "провалится" во вторую часть запроса.
Важный нюанс: у этого метода есть существенный минус. Если в процессе дальнейшей разработки вы случайно измените запрос, система может перестроить список полей, и все вручную расставленные ограничения на вкладке "Поля" могут сброситься. Поэтому первые два способа (использование конструкции расширения языка СКД и "Набор данных - объединение") являются более надежными и профессиональными подходами.
Используйте рассмотренные техники в зависимости от сложности вашей схемы. Для простых объединений отлично подойдут фигурные скобки, а для сложных структур с разной логикой фильтрации — создание составного набора данных-объединения.