В практике разработки на платформе 1С:Предприятие часто возникает задача создания универсального отчета или обработки, где пользователю предоставляется несколько полей для фильтрации данных. Основная сложность заключается в реализации логики «необязательных параметров»: если пользователь заполнил фильтр, программа должна отобрать данные по этому значению, а если оставил поле пустым — вывести все записи без исключения по данному критерию.
Рассмотрим подробно, как реализовать такую логику в языке запросов 1С, проанализируем эффективность различных подходов и выберем наиболее оптимальные методы для различных ситуаций.
Разберем классический подход, который часто применяется, когда текст запроса статичен и не формируется динамически в коде. Суть метода заключается в том, чтобы внутри условия ГДЕ проверить значение параметра на «пустоту». Если параметр не задан, условие должно всегда возвращать ИСТИНА.
Проанализируем пример кода, реализующий этот алгоритм:
"ВЫБРАТЬ
| ИсторияРасценок.Регистратор,
| ИсторияРасценок.Период,
| ИсторияРасценок.Работа,
| ИсторияРасценок.Цена
|ИЗ
| РегистрСведений.ИсторияРасценок КАК ИсторияРасценок
|ГДЕ
| ВЫБОР
| КОГДА &Работа = ЗНАЧЕНИЕ(Справочник.Работы.ПустаяСсылка)
| ТОГДА ИСТИНА
| ИНАЧЕ ИсторияРасценок.Работа = &Работа
| КОНЕЦ
| И ВЫБОР
| КОГДА &Груз = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ТОГДА ИСТИНА
| ИНАЧЕ ИсторияРасценок.Груз = &Груз
| КОНЕЦ"
Как работает эта логика? Когда платформа 1С выполняет запрос, она вычисляет условие для каждой строки. Если в параметр &Работа передана пустая ссылка, блок ВЫБОР сразу возвращает ИСТИНА, и фильтрация по конкретному значению работы не производится. Если же параметр заполнен, выполняется сравнение поля таблицы с переданным значением.
Важный нюанс: при проверке на пустое значение необходимо учитывать тип данных. Для ссылочных типов (Справочники, Документы) мы используем ЗНАЧЕНИЕ(...ПустаяСсылка), а для простых типов или составных полей может потребоваться проверка на НЕОПРЕДЕЛЕНО или NULL.
Существует более лаконичный способ записи того же самого условия. Мы можем использовать оператор В, передав в него массив из двух элементов: само значение поля и признак «пустоты». Однако в контексте параметров запроса это выглядит еще проще — мы проверяем, входит ли наш параметр в список, состоящий из значения поля в базе и «пустого» значения.
Посмотрим на пример сокращенной записи:
"ВЫБРАТЬ
| ИсторияРасценок.Работа,
| ИсторияРасценок.Цена
|ИЗ
| РегистрСведений.ИсторияРасценок КАК ИсторияРасценок
|ГДЕ
| &Работа В (ЗНАЧЕНИЕ(Справочник.Работы.ПустаяСсылка), ИсторияРасценок.Работа)
| И &Груз В (ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка), ИсторияРасценок.Груз)"
Выясним причину популярности этого метода. Он значительно сокращает объем текста запроса, делая его более читаемым. Если параметр &Работа пустой, то условие превращается в ПустаяСсылка В (ПустаяСсылка, Поле), что всегда ИСТИНА. Если параметр заполнен конкретной ссылкой, условие выполняется только тогда, когда эта ссылка совпадает с ИсторияРасценок.Работа.
Хотя предыдущие методы удобны, у них есть существенный недостаток — производительность. Использование ВЫБОР или сложных условий с ИЛИ (которые СУБД видит за оператором В) часто мешает оптимизатору SQL использовать индексы таблиц. Это может привести к полному сканированию таблицы (Full Scan), что критично для больших регистров.
Профессиональный подход заключается в динамической сборке условия ГДЕ в коде на языке 1С. Рассмотрим, как это сделать правильно:
ТекстУсловия = "";
МассивУсловий = Новый Массив;
Если ЗначениеЗаполнено(Работа) Тогда
МассивУсловий.Добавить("ИсторияРасценок.Работа = &Работа");
КонецЕсли;
Если ЗначениеЗаполнено(Груз) Тогда
МассивУсловий.Добавить("ИсторияРасценок.Груз = &Груз");
КонецЕсли;
Если МассивУсловий.Количество() > 0 Тогда
ТекстУсловия = "ГДЕ " + СтрСоединить(МассивУсловий, " И ");
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ
| ИсторияРасценок.Цена
|ИЗ
| РегистрСведений.ИсторияРасценок КАК ИсторияРасценок
|" + ТекстУсловия;
В этом случае в итоговый запрос попадут только те фильтры, которые действительно необходимы. Если параметры не заполнены, секция ГДЕ будет полностью отсутствовать, и запрос отработает максимально быстро.
Если задача стоит в рамках разработки отчета или сложной обработки, использование Системы компоновки данных является самым правильным решением. СКД изначально спроектирована для работы с динамическими отборами.
Разберем основные преимущества использования СКД для фильтрации:
{ГДЕ Поле = &Параметр}. Если параметр не заполнен, условие внутри скобок будет проигнорировано платформой автоматически.Даже если вам не нужно выводить отчет, вы можете программно инициализировать схему компоновки, установить настройки отбора и выгрузить результат в ТаблицуЗначений. Это обеспечит максимальную производительность и чистоту кода.
Проанализируем важный технический аспект: разницу между пустой ссылкой и отсутствием значения. В 1С поле может содержать:
Справочник.Номенклатура.ПустаяСсылка()).Если в вашем регистре поле может принимать значение NULL, обычное сравнение ИсторияРасценок.Объект = &Объект вернет ЛОЖЬ, даже если &Объект тоже NULL (в 1С NULL не равен NULL). В таких случаях рекомендуется использовать функцию ЕСТЬNULL в тексте запроса, чтобы привести значения к единому типу перед сравнением.
Подведем итог и определим, какой метод использовать в зависимости от ситуации:
Используя эти приемы, мы создаем гибкие и надежные механизмы поиска и фильтрации данных, которые корректно ведут себя при любом наборе заполненных параметров.