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