Как реализовать необязательные отборы в запросе 1С по аналогии с СКД

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

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

Способ 1. Использование логических условий «ИЛИ» в тексте запроса

Это самый простой и распространенный метод, который не требует программной сборки текста запроса. Идея заключается в том, чтобы условие в секции ГДЕ возвращало ИСТИНА либо при совпадении значения с параметром, либо в случае, если сам параметр не заполнен (равен пустой ссылке).

Разберем по шагам реализацию этого метода на примере отбора по Организации, Подразделению и Сотруднику. Проанализируем следующий код запроса:


ВЫБРАТЬ
    Сотрудники.Ссылка КАК Сотрудник,
    Сотрудники.Подразделение КАК Подразделение,
    Сотрудники.Организация КАК Организация
ИЗ
    Справочник.Сотрудники КАК Сотрудники
ГДЕ
    (&Сотрудник = ЗНАЧЕНИЕ(Справочник.Сотрудники.ПустаяСсылка) ИЛИ Сотрудники.Ссылка = &Сотрудник)
    И (&Подразделение = ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) ИЛИ Сотрудники.Подразделение = &Подразделение)
    И (&Организация = ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка) ИЛИ Сотрудники.Организация = &Организация)

Как это работает: если пользователь не выбрал сотрудника, параметр &Сотрудник будет содержать пустую ссылку. Выражение &Сотрудник = ЗНАЧЕНИЕ(...) станет истинным, и все условие в скобках будет выполняться для каждой строки таблицы, фактически отключая фильтр по сотруднику. Если же сотрудник выбран, первая часть условия будет ложной, и сработает вторая часть — Сотрудники.Ссылка = &Сотрудник. Аналогичная логика применяется к остальным полям.

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

Способ 2. Динамическое построение текста запроса

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

Рассмотрим пример функции, которая собирает текст запроса в зависимости от заполненности реквизитов на форме:


ТекстУсловий = "";
МассивУсловий = Новый Массив;

Если ЗначениеЗаполнено(Объект.Организация) Тогда
    МассивУсловий.Добавить("Сотрудники.Организация = &Организация");
КонецЕсли;

Если ЗначениеЗаполнено(Объект.Подразделение) Тогда
    МассивУсловий.Добавить("Сотрудники.Подразделение = &Подразделение");
КонецЕсли;

Если ЗначениеЗаполнено(Объект.Сотрудник) Тогда
    МассивУсловий.Добавить("Сотрудники.Ссылка = &Сотрудник");
КонецЕсли;

Если МассивУсловий.Количество() > 0 Тогда
    ТекстУсловий = "ГДЕ " + СтрСоединить(МассивУсловий, " И ");
КонецЕсли;

ТекстЗапроса = 
"ВЫБРАТЬ
|   Сотрудники.Ссылка
|ИЗ
|   Справочник.Сотрудники КАК Сотрудники
|" + ТекстУсловий;

Запрос = Новый Запрос(ТекстЗапроса);
// Установка параметров
Запрос.УстановитьПараметр("Организация", Объект.Организация);
Запрос.УстановитьПараметр("Подразделение", Объект.Подразделение);
Запрос.УстановитьПараметр("Сотрудник", Объект.Сотрудник);

В данном случае мы используем Массив для хранения строк условий и функцию СтрСоединить для их склейки через оператор И. Этот подход считается наиболее «чистым» с точки зрения SQL, так как в итоговый запрос попадают только необходимые инструкции, что позволяет оптимизатору СУБД строить максимально эффективные планы выполнения.

Способ 3. Программное использование схемы запроса

Для более сложных случаев, когда запрос содержит вложенные запросы или объединения, ручная склейка строк может привести к ошибкам. В платформе 1С существует объект СхемаЗапроса, который позволяет управлять структурой запроса как объектной моделью. Посмотрим, как можно добавить отбор через этот механизм.

Проанализируем пример кода:


Схема = Новый СхемаЗапроса;
Схема.УстановитьТекстЗапроса(ИсходныйТекст);

ЗапросВыбора = Схема.ПакетЗапросов[0]; // Работаем с первым запросом в пакете

Если ЗначениеЗаполнено(Объект.Организация) Тогда
    ЗапросВыбора.Отбор.Добавить("Организация = &Организация");
КонецЕсли;

Запрос = Новый Запрос;
Запрос.Текст = Схема.ПолучитьТекстЗапроса();
Запрос.УстановитьПараметр("Организация", Объект.Организация);

Объект СхемаЗапроса гарантирует, что синтаксис запроса останется корректным, даже если вы динамически добавляете множество полей и условий.

Связи параметров выбора на форме

Чтобы пользователю было удобно работать с такими отборами, важно правильно настроить интерфейс. В сообщении 12 автор темы задал важный вопрос: как сделать так, чтобы при выборе подразделения отображались только подразделения выбранной организации? Это решается не в запросе, а в настройках формы (или метаданных).

Разберем настройку Связи параметров выбора:

  1. Откройте форму вашей обработки или свойства реквизита в конфигураторе.
  2. Найдите реквизит Подразделение.
  3. В свойстве Связи параметров выбора (Choice Parameter Links) нажмите на кнопку выбора.
  4. Добавьте новую связь: выберите поле Отбор.Владелец (поскольку для подразделений владельцем обычно является организация) и укажите в качестве источника поле Организация.

После этой настройки 1С автоматически будет фильтровать список подразделений при открытии формы выбора, передавая туда выбранную организацию. Аналогично можно настроить связь для сотрудника, чтобы при выборе сотрудника отбор шел по подразделению или организации.

Использование СКД программно

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

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

Подведем итог: для простых задач идеально подходит метод с ИЛИ в тексте запроса. Для высоконагруженных систем или сложных условий лучше использовать динамическую сборку текста или СхемаЗапроса. И не забывайте про визуальное удобство для пользователя, настраивая связи параметров выбора на форме.

← На главную