Друзья, обработка представляет собой обертку схемы запросов, позволяющую редактировать запрос через объектную модель. В редакторе запросов реализовано:
- Добавление отборов, полей выборки, соединений, параметров виртуальных таблиц
- Добавление "подзапросов", запросов и пакетов запросов
- Добавление "подзапросов" выполняемых в привилегированном режиме
- Выполнение порционной выборки данных (спасибо за реализацию, Алексею Козленко @AIKozlenko)
Базовый запрос это выборка минимального набора полей необходимого для выполнения сортировки или дальнейшей расшифровки. В основном это "Ссылка" и все поля по которым необходимо выполнение настройки сортировки.
1. Выполним инициализацию редактора запросов с загрузкой базового запроса.
// Базовый запрос
БазовыйЗапросТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1000
| Справочник1.Ссылка КАК Ссылка,
| Справочник1.Реквизит1 КАК Реквизит1
|ИЗ
| Справочник.Справочник1 КАК Справочник1
|
|УПОРЯДОЧИТЬ ПО
| Реквизит1";
БазовыйЗапрос = Новый Запрос(БазовыйЗапросТекст);
// Создадим редактор запросов
РедакторЗапросов = Обработки.га_РедакторЗапросов.Инициализировать(БазовыйЗапрос);
2. Выполним добавление отбора в последний запрос.
// Добавим отбор
Значения = Новый Массив;
Значения.Добавить("Значение1");
Значения.Добавить("Значение2");
РедакторЗапросов.ПоследнийЗапросУсловиеДобавить("Справочник1.Реквизит1", "=", Значения);
Если условие сложное, возможно добавить напрямую выражением схемы запроса:
РедакторЗапросов.ПоследнийЗапросУсловиеВыражениеСхемыЗапросаДобавить("Справочник1.Реквизит1 В(&Реквизит1_0)");
Итоговый текст запроса:
3. Выполним соединение с дополнительной таблицей с установкой отбора.
// Добавим подзапрос и установим отбор
ПодзапросТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегистрСведений1 КАК РегистрСведений1
| ПО БазовыйЗапрос.Ссылка = РегистрСведений1.Измерение1
|ГДЕ
| РегистрСведений1.Ресурс1 = &Ресурс1";
Подзапрос = Новый Запрос(ПодзапросТекст);
Подзапрос.УстановитьПараметр("Ресурс1", "Значение1");
РедакторЗапросов.ПодзапросДобавить(Подзапрос);
РедакторЗапросов.ПоследнийЗапросУсловиеДобавить("РегистрСведений1.Ресурс2", ">", "Значение2");
Базовый запрос будет помещен во временную таблицу с применением "подзапроса" и удалением временной таблицы. Выражения сортировки и ограничения количества перейдут в новый запрос.
Итоговый текст запроса:
4. Выполним создание пакета временных таблиц с последующим использованием в "подзапросе".
// Добавим пакет временных таблиц, добавим подзапрос и установим отбор
ПакетВременныхТаблицТекст =
"ВЫБРАТЬ
| РегистрСведений2.Измерение1 КАК Измерение1,
| РегистрСведений2.Измерение2 КАК Измерение2,
| РегистрСведений2.Измерение3 КАК Измерение3
|ПОМЕСТИТЬ ДополнительныеДанные
|ИЗ
| РегистрСведений.РегистрСведений2 КАК РегистрСведений2
|ГДЕ
| РегистрСведений2.Измерение1 В
| (ВЫБРАТЬ
| БазовыйЗапрос.Ссылка КАК Ссылка
| ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос)";
ПодзапросТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ДополнительныеДанные КАК ДополнительныеДанные
| ПО БазовыйЗапрос.Ссылка = ДополнительныеДанные.Измерение1";
ПакетВременныхТаблиц = Новый Запрос(ПакетВременныхТаблицТекст);
Подзапрос = Новый Запрос(ПодзапросТекст);
РедакторЗапросов.ПакетВременныхТаблицИПодзапросДобавить(ПакетВременныхТаблиц, Подзапрос);
РедакторЗапросов.ПоследнийЗапросУсловиеДобавить("ДополнительныеДанные.Измерение2", "=", "Значение1");
Итоговый текст запроса:
5. При добавлении "подзапросов" запрос выборки постоянно смещается, но доступ к базовому запросу сохраняется, в любой момент можно добавить отбор в самый первый запрос:
// Добавим отбор в базовый запрос
РедакторЗапросов.БазовыйЗапросУсловиеДобавить("Справочник1.Реквизит2", "=", "Значение1");
Текст "подзапроса" кешируется, поэтому также сохраняется доступ и к ним
// Кеширование подзапроса
ПодзапросТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегистрСведений1 КАК РегистрСведений1
| ПО БазовыйЗапрос.Ссылка = РегистрСведений1.Измерение1
|ГДЕ
| РегистрСведений1.Ресурс1 = &Ресурс1";
Подзапрос = Новый Запрос(ПодзапросТекст);
ИндексПакета = РедакторЗапросов.ПодзапросДобавить(Подзапрос);
РедакторЗапросов.ЗапросУсловиеДобавить(ИндексПакета, "РегистрСведений1.Ресурс3", "<>", "Значение1");
Итоговый текст запроса:
6. При необходимости выполнение "подзапроса" возможно выполнить в привилегированном режиме.
// Выполнение подзапроса в привилегированном режиме
ПодзапросТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
| БазовыйЗапрос.*
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегистрСведений3 КАК РегистрСведений3
| ПО БазовыйЗапрос.Ссылка = РегистрСведений3.Измерение1";
Подзапрос = Новый Запрос(ПодзапросТекст);
РедакторЗапросов.ПодзапросВПривилегированномРежимеДобавить(Подзапрос);
Итоговый текст запроса:
7. После окончания редактирования возможно получить выборку или поместить результат в менеджер временных таблиц для дальнейшего использования.
// Получим выборку
Выборка = РедакторЗапросов.СкомпоноватьИВыбрать();
// Получим выборку и поместим результат во временную таблицу
ВыборкаОписание = РедакторЗапросов.СкомпоноватьИВыбратьСПомещениемВоВременнуюТаблицу();
// ВыборкаОписание.Выборка
// ВыборкаОписание.МенеджерВременныхТаблиц
// ВыборкаОписание.ТаблицаВМенеджере
8. Редактор запросов возможно использовать для порционной выборки данных. Базовый запрос выполнится и будет помещен во временную таблицу целиком, а запрос расшифровки будет скользить по базовому в цикле, с установленной порцией.
// Базовый запрос
БазовыйЗапросТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Справочник1.Ссылка КАК Ссылка,
| Справочник1.Реквизит1 КАК Реквизит1
|ИЗ
| Справочник.Справочник1 КАК Справочник1
|
|УПОРЯДОЧИТЬ ПО
| Реквизит1";
// Запрос расшифровки
ЗапросРасшифровкиТекст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| БазовыйЗапрос.Ссылка КАК Ссылка,
| РегистрСведений2.Измерение1 КАК Измерение1,
| РегистрСведений2.Измерение2 КАК Измерение2,
| РегистрСведений2.Измерение3 КАК Измерение3,
| РегистрСведений2.Ресурс1 КАК Ресурс1
|ИЗ
| БазовыйЗапрос КАК БазовыйЗапрос
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РегистрСведений2 КАК РегистрСведений2
| ПО БазовыйЗапрос.Ссылка = РегистрСведений2.Измерение1";
БазовыйЗапрос = Новый Запрос(БазовыйЗапросТекст);
ЗапросРасшифровки = Новый Запрос(ЗапросРасшифровкиТекст);
РедакторЗапросов = Обработки.га_РедакторЗапросов.Инициализировать(БазовыйЗапрос);
Выборка = Неопределено;
Пока РедакторЗапросов.СкомпоноватьИВыбратьСОбходомПостранично(Выборка, ОбходРезультатаЗапроса.Прямой, 100, ЗапросРасшифровки) Цикл
// Выборка.Ссылка
// Выборка.Измерение1
// Выборка.Измерение2
// Выборка.Измерение3
// Выборка.Ресурс1
КонецЦикла;
Как видите, все просто, данная разработка в помощь!
Обработка является частью модуля Стандартные подсистемы.
Проект и исходный код доступен на GitLab.
-----
Требования:
- Обработка предназначена для версии платформы >= 8.3.13, тестировалась на 8.3.21.1895
- БСП, процедура "ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру
-----
Ссылки:
- Проект в GitLab
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.10.243