Как реализовать условный отбор в запросе 1С в зависимости от флага (галочки) на форме?

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

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

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

Вариант 1. Условная конструкция ВЫБОР КОГДА в секции ГДЕ

Давайте начнем с разбора классического подхода, который часто первым приходит в голову начинающим разработчикам. Идея заключается в использовании конструкции ВЫБОР КОГДА непосредственно внутри секции ГДЕ нашего запроса.

Рассмотрим пример кода, реализующий эту логику:


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

Давайте разберем по шагам, как работает это условие:

  1. В параметр &ГалочкаУстановлена мы передаем булево значение с формы (Истина или Ложь).
  2. Если пользователь взвел флаг на форме, параметр принимает значение Истина. Запрос переходит по ветке ТОГДА и начинает проверять физическое равенство поля ТипОтгрузки нашему значению перечисления Поставщику.
  3. Если флаг снят, параметр равен Ложь. Запрос уходит в ветку ИНАЧЕ, которая возвращает значение ИСТИНА.
  4. В итоге условие превращается в тождество: ИСТИНА = ИСТИНА. База данных просто игнорирует этот фильтр и отдает нам все документы по выбранной организации за указанный период.

Важное предупреждение о производительности: Несмотря на то что данный код полностью работоспособен и решает задачу «в лоб», согласно официальным стандартам разработки 1С использовать конструкцию ВЫБОР КОГДА в секции ГДЕ крайне не рекомендуется. СУБД (будь то MS SQL Server, PostgreSQL или любая другая база данных) из-за такой динамической условной логики не всегда способна корректно построить план выполнения запроса. Вместо быстрого поиска по индексам (Index Seek) СУБД может выбрать полное сканирование таблицы (Table Scan), что на больших базах данных неминуемо приведет к сильным зависаниям системы.

Вариант 2. Оптимальное логическое условие с использованием ИЛИ

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

Заменим конструкцию ВЫБОР КОГДА на следующее изящное логическое выражение:


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

Выясним логику работы этой конструкции:

  1. Мы ввели параметр &ОтборПоТипу, куда транслируем состояние нашей галочки с формы.
  2. Если галочка снята (значение Ложь), то выражение НЕ &ОтборПоТипу превращается в НЕ Ложь, то есть в Истина. Поскольку левая часть логического оператора ИЛИ стала истинной, вся скобка автоматически признается истинной. СУБД даже не пытается анализировать правую часть выражения и возвращает все имеющиеся документы без оглядки на тип отгрузки.
  3. Если галочка установлена (значение Истина), то левая часть НЕ Истина превращается в Ложь. Чтобы вся скобка вернула истину, СУБД обязана вычислить и проверить правую часть условия: ОтгрузкаТовара.ТипОтгрузки = Поставщику. Происходит жесткая и корректная фильтрация данных.

Такой подход обрабатывается оптимизатором СУБД гораздо дружелюбнее, чем тяжеловесный ВЫБОР КОГДА, и часто является отличным компромиссом для небольших и средних по объему таблиц базы данных.

Вариант 3. Идеальный по производительности — динамический текст запроса

Если мы работаем с высоконагруженными системами и огромными таблицами (содержащими миллионы записей), то лучшим решением со стороны СУБД будет отправка максимально чистого SQL-запроса, в котором нет никаких лишних логических ветвлений в секции ГДЕ.

Для этого мы воспользуемся динамическим конструированием текста запроса на встроенном языке 1С. Посмотрим на пример правильной и аккуратной реализации этого механизма:


// Задаем базовую, гарантированную часть запроса
ТекстЗапроса = 
"ВЫБРАТЬ
|	ОтгрузкаТовара.Ссылка КАК Документ
|ИЗ
|	Документ.ОтгрузкаТовара КАК ОтгрузкаТовара
|ГДЕ
|	ОтгрузкаТовара.Дата МЕЖДУ &ПериодНачало И &ПериодКонец
|	И ОтгрузкаТовара.Организация = &Организация";

Запрос = Новый Запрос;

// Анализируем состояние галочки на форме и динамически добавляем условие
Если ЭтаФорма.ТипОтгрузки Тогда 
	ТекстЗапроса = ТекстЗапроса + "
	|	И ОтгрузкаТовара.ТипОтгрузки = &ТипОтгрузки";
	Запрос.УстановитьПараметр("ТипОтгрузки", Перечисления.ТипОтгрузки.Поставщику);
КонецЕсли;

Запрос.Текст = ТекстЗапроса;

// Установка стандартных параметров
Запрос.УстановитьПараметр("Организация", Справочники.Организации.НайтиПоНаименованию("МояОрганизация"));
Запрос.УстановитьПараметр("ПериодНачало", ПериодНачало);
Запрос.УстановитьПараметр("ПериодКонец", КонецДня(ПериодКонец));

РезультатЗапроса = Запрос.Выполнить();

Проанализируем преимущества и недостатки этого метода:

Вариант 4. Технологичное решение для отчетов и списков — СКД

Если вы разрабатываете отчет на Системе компоновки данных или настраиваете динамический список для управляемой формы, то самым правильным и профессиональным решением будет использование встроенного расширения языка запросов СКД.

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


ВЫБРАТЬ
	ОтгрузкаТовара.Ссылка КАК Документ
ИЗ
	Документ.ОтгрузкаТовара КАК ОтгрузкаТовара
ГДЕ
	ОтгрузкаТовара.Дата МЕЖДУ &ПериодНачало И &ПериодКонец
	И ОтгрузкаТовара.Организация = &Организация
	{И ОтгрузкаТовара.ТипОтгрузки = &ТипОтгрузки}

Как работает этот механизм?

  1. Если пользователь в настройках отчета или на форме динамического списка заполнил параметр &ТипОтгрузки (или взвел соответствующий флаг использования параметра), СКД автоматически «вклеит» данное условие в итоговый SQL-запрос.
  2. Если параметр пустой или флаг использования снят, СКД полностью и бесследно вырежет строку И ОтгрузкаТовара.ТипОтгрузки = &ТипОтгрузки из финального текста запроса перед его отправкой на сервер СУБД.

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

Вариант 5. Прием с передачей значения Неопределено

Иногда программисты хотят избежать заведения лишних булевых параметров под галочки. В таком случае можно использовать изящный прием с передачей значения Неопределено (или NULL) непосредственно в параметр отбора.

Посмотрим на пример реализации данного подхода:

ГДЕ (&ТипОтгрузки = Неопределено ИЛИ ОтгрузкаТовара.ТипОтгрузки = &ТипОтгрузки)

В коде встроенного языка BSL мы управляем этим условием следующим образом:


// Если галочка установлена, передаем конкретный тип отгрузки, иначе — Неопределено
ЗначениеПараметра = ?(ЭтаФорма.ТипОтгрузки, Перечисления.ТипОтгрузки.Поставщику, Неопределено);
Запрос.УстановитьПараметр("ТипОтгрузки", ЗначениеПараметра);

Если галочка не взведена, в параметр попадает Неопределено. В запросе условие &ТипОтгрузки = Неопределено возвращает Истину, и СУБД игнорирует проверку поля ТипОтгрузки, возвращая все имеющиеся в базе документы.

Резюме и рекомендации

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

  1. Используйте Вариант 3 (Динамический запрос) для критически важных участков кода, выполняющихся в циклах, транзакциях или при работе с высоконагруженными таблицами.
  2. Используйте Вариант 4 (Фигурные скобки в СКД) во всех отчетах, схемах компоновки данных и при работе с динамическими списками управляемых форм.
  3. Используйте Вариант 2 (Логическое ИЛИ) или Вариант 5 (Проверка на Неопределено) для простых и быстрых доработок небольших справочников и документов, когда скорость написания кода важнее тонкой оптимизации планов SQL.
  4. Старайтесь полностью избегать Варианта 1 (ВЫБОР КОГДА) в секции ГДЕ, чтобы не создавать потенциальных проблем с производительностью СУБД в будущем.
← На главную