Друзья, иногда в некоторых списках необходимо поддерживать сотни фильтров с соединением со множеством таблиц. Обычно это решается формированием динамического запроса в зависимости от установленных отборов, но очень легко это может превратиться в громоздкую и неуправляемую конструкцию. Один фильтр зависит от соединений, которые накладываются другими, внезапные дублирования строк или такие же неожиданные проседания по производительности. От всего этого спасает фильтрация через подзапросы в Редакторе запросов, которая максимально изолирует отборы друг от друга.
Процедура Пример3НаСервере()
БазовыйЗапросТекст =
"ВЫБРАТЬ
| Пользователи.Ссылка КАК Ссылка
|ИЗ
| Справочник.Пользователи КАК Пользователи";
БазовыйЗапрос = Новый Запрос(БазовыйЗапросТекст);
// Инициализируем редактор запросов
РедакторЗапроса = Обработки.сп_РедакторЗапросов.Инициализировать(БазовыйЗапрос);
// Выполним пакетную фильтрацию
ПакетнаяФильтрацияОтборыПрименить(РедакторЗапроса, "СрокДействия", ">", Дата(2025, 1, 1));
ПакетнаяФильтрацияОтборыПрименить(РедакторЗапроса, "АвторФайла", "=", "СсылкаНаФайл");
ПакетнаяФильтрацияОтборыПрименить(РедакторЗапроса, "АвторПроцессов", "=", "СсылкаНаПроцесс");
Выборка = РедакторЗапроса.СкомпоноватьИВыбрать();
Пока Выборка.Следующий() Цикл
КонецЦикла;
КонецПроцедуры
Процедура ПакетнаяФильтрацияОтборыПрименить(РедакторЗапроса, ФильтрПоле, ФильтрУсловиеСравения, ФильтрЗначение)
Если ФильтрПоле = "СрокДействия" Тогда
ПодзапросТекст =
"ВЫБРАТЬ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОПользователях КАК СведенияОПользователях
| ПО БазовыйЗапрос.Ссылка = СведенияОПользователях.Пользователь";
Подзапрос = Новый Запрос(ПодзапросТекст);
РедакторЗапроса.ПодзапросДобавить(Подзапрос);
РедакторЗапроса.ПоследнийЗапросУсловиеДобавить("СведенияОПользователях.СрокДействия", ФильтрУсловиеСравения, ФильтрЗначение);
ИначеЕсли ФильтрПоле = "АвторФайла" Тогда
ПодзапросТекст =
"ВЫБРАТЬ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
| ПО БазовыйЗапрос.Ссылка = СведенияОФайлах.Автор";
Подзапрос = Новый Запрос(ПодзапросТекст);
РедакторЗапроса.ПодзапросДобавить(Подзапрос);
РедакторЗапроса.ПоследнийЗапросУсловиеДобавить("СведенияОФайлах.Файл", ФильтрУсловиеСравения, ФильтрЗначение);
ИначеЕсли ФильтрПоле = "АвторПроцессов" Тогда
ПодзапросТекст =
"ВЫБРАТЬ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ БизнесПроцесс.Задание КАК Задание
| ПО БазовыйЗапрос.Ссылка = Задание.Автор";
Подзапрос = Новый Запрос(ПодзапросТекст);
РедакторЗапроса.ПодзапросДобавить(Подзапрос);
РедакторЗапроса.ПоследнийЗапросУсловиеДобавить("Задание.Ссылка", ФильтрУсловиеСравения, ФильтрЗначение);
КонецЕсли;
КонецПроцедуры
При компоновке запроса, его текст будет выглядеть следующим образом:
"ВЫБРАТЬ
| Пользователи.Ссылка КАК Ссылка
|ПОМЕСТИТЬ БазовыйЗапрос_1
|ИЗ
| Справочник.Пользователи КАК Пользователи
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| БазовыйЗапрос_1.Ссылка КАК Ссылка
|ПОМЕСТИТЬ БазовыйЗапрос_2
|ИЗ
| БазовыйЗапрос_1 КАК БазовыйЗапрос_1
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОПользователях КАК СведенияОПользователях
| ПО БазовыйЗапрос_1.Ссылка = СведенияОПользователях.Пользователь
|ГДЕ
| СведенияОПользователях.СрокДействия > &СрокДействия_1
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ БазовыйЗапрос_1
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| БазовыйЗапрос_2.Ссылка КАК Ссылка
|ПОМЕСТИТЬ БазовыйЗапрос_4
|ИЗ
| БазовыйЗапрос_2 КАК БазовыйЗапрос_2
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
| ПО БазовыйЗапрос_2.Ссылка = СведенияОФайлах.Автор
|ГДЕ
| СведенияОФайлах.Файл = &Файл_3
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ БазовыйЗапрос_2
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| БазовыйЗапрос_4.Ссылка КАК Ссылка
|ИЗ
| БазовыйЗапрос_4 КАК БазовыйЗапрос_4
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ БизнесПроцесс.Задание КАК Задание
| ПО БазовыйЗапрос_4.Ссылка = Задание.Автор
|ГДЕ
| Задание.Ссылка = &Ссылка_5
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ БазовыйЗапрос_4"
Но при простоте обслуживания и реализации новых отборов, есть зависимость производительности от селективности примененных фильтров. В том случае если отборы высокоселективны, то во временные таблицы могут начать помещаться десятки тысяч строк и даже кочевать из одной временной таблицы в другую. Чтобы этого избежать, можно применить циклическую вложенную фильтрацию, реализованную в Редакторе запросов. Для этого перед компоновкой запроса необходимо выполнить команду:
РедакторЗапроса.ЦиклическаяВложеннаяФильтрацияПрименить();
И текст запроса будет выглядеть следующим образом:
"ВЫБРАТЬ
| БазовыйЗапрос_4.Ссылка КАК Ссылка
|ИЗ
| Справочник.Пользователи КАК БазовыйЗапрос_4
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ БизнесПроцесс.Задание КАК Задание
| ПО БазовыйЗапрос_4.Ссылка = Задание.Автор
|ГДЕ
| Задание.Ссылка = &Ссылка_5
| И БазовыйЗапрос_4.Ссылка В
| (ВЫБРАТЬ
| БазовыйЗапрос_2.Ссылка КАК Ссылка
| ИЗ
| Справочник.Пользователи КАК БазовыйЗапрос_2
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
| ПО
| БазовыйЗапрос_2.Ссылка = СведенияОФайлах.Автор
| ГДЕ
| СведенияОФайлах.Файл = &Файл_3
| И БазовыйЗапрос_2.Ссылка В
| (ВЫБРАТЬ
| БазовыйЗапрос_1.Ссылка КАК Ссылка
| ИЗ
| Справочник.Пользователи КАК БазовыйЗапрос_1
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОПользователях КАК СведенияОПользователях
| ПО
| БазовыйЗапрос_1.Ссылка = СведенияОПользователях.Пользователь
| ГДЕ
| СведенияОПользователях.СрокДействия > &СрокДействия_1
| И БазовыйЗапрос_1.Ссылка В
| (ВЫБРАТЬ
| Пользователи.Ссылка КАК Ссылка
| ИЗ
| Справочник.Пользователи КАК Пользователи)))"
Каждый подзапрос помещается во вложенный запрос и применяется в отборах последующего, что исключает использование временных таблиц и дает кратный прирост производительности запроса в условиях высокоселективных отборов.
Как видите, все просто, Редактор запросов в помощь!
-----
Ссылки:
- Обработка на Инфостарт
Вступайте в нашу телеграмм-группу Инфостарт