Заказы на доработку 1С (сервис удаленной работы)

Хранилище

База знаний
Бесплатные отчеты, обработки, конфигурации, внешние компоненты для 1С Статьи, описание работы, методики по работе с 1С

Здравствуйте, гость ( Вход | Зарегистрироваться )



> Пакетные запросы          
Vofka Подменю пользователя
сообщение 28.02.11, 9:21
Сообщение #1

У нас здесь своя атмосфера...
***********
Группа: Основатель
Сообщений: 13948
Из: Киев
Спасибо сказали: 4514 раз
Рейтинг: 3635.6

История развития запросов

Простые запросы

Разберем, как изменялся (скорее дополнялся) синтаксис текстов запросов на простом примере: Проводится документ Расходная содержащая в табличной части Товары список продаваемых товаров и количество. При проведении такого документа необходимо обеспечить контроль отрицательных остатков хранящихся в регистре накопления остатков ОстаткиТоваров.

Структура конфигурации представлена на рисунке.

Прикрепленный файл  1.png ( 16,22 килобайт ) Кол-во скачиваний: 65


Сформируем запрос к табличной части документа и виртуальной таблице Остатки регистра накопления. Учтем возможные дубли строк в документе, для этого произведем группирование записей.

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

   Запрос = Новый Запрос;
   Запрос.Текст = "
   |ВЫБРАТЬ
   |   Док.Номенклатура,
   |   СУММА(Док.Количество) КАК Док_Количество,
   |   МИНИМУМ(ЕСТЬNULL(Рег.КоличествоОстаток,0)) КАК Рег_Количество
   |
   |ИЗ
   |   Документ.Расходная.Товары КАК Док
   |   ЛЕВОЕ СОЕДИНЕНИЕ
   |     РегистрНакопления.ОстаткиТоваров.Остатки() КАК Рег
   |   ПО
   |     Док.Номенклатура = Рег.Номенклатура
   |
   |ГДЕ
   |   Ссылка = &Ссылка
   |СГРУППИРОВАТЬ ПО Док.Номенклатура";

   Запрос.УстановитьПараметр("Ссылка", Ссылка);
   РезультатЗапроса = Запрос.Выполнить();
   Выборка = РезультатЗапроса.Выбрать();

   Пока Выборка.Следующий() Цикл

   //Проверка отрицательных остатков

   //Проведение по регистру

   КонецЦикла;

КонецПроцедуры


Естественно приведенный запрос абсолютно не оптимален. С помощью вложенных запросов оптимизируем его: Произведем группирование табличной части документа до соединения с таблицей остатков, в параметры виртуальной таблицы передадим список товаров как значение условия для расчета остатков. В итоге наш запрос примет следующий вид:

|ВЫБРАТЬ
| Док.Номенклатура,
| Док.Количество КАК Док_Количество,
| ЕСТЬNULL(Рег.КоличествоОстаток,0) КАК Рег_Количество
|
|ИЗ
| (ВЫБРАТЬ
|   Номенклатура, СУММА(Количество) КАК Количество
|  ИЗ
|   Документ.Расходная.Товары
|  ГДЕ
|   Ссылка = &Ссылка
|  СГРУППИРОВАТЬ ПО Номенклатура) КАК Док
|
|  ЛЕВОЕ СОЕДИНЕНИЕ
|   РегистрНакопления.ОстаткиТоваров.Остатки( , Номенклатура В
|                                              (ВЫБРАТЬ РАЗЛИЧНЫЕ
|                                                Номенклатура
|                                               ИЗ
|                                                Документ.Расходная.Товары
|                                               ГДЕ
|                                                Ссылка = &Ссылка)) КАК Рег
|  ПО
|   Док.Номенклатура = Рег.Номенклатура";


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

Временные таблицы

Не помню уже с какого релиза в запросах стало можно использовать временные таблицы. Для этого используется объект «Менеджер временных таблиц». Фактически менеджер временных таблиц описывает пространство имен временных таблиц и отвечает за их создание и уничтожение в базе данных.

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

Перепишем запрос для использования временных таблиц. Во временные таблицы поместим сгруппированную табличную часть документа и список товаров для фильтра виртуальных таблиц:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

МВТ = Новый МенеджерВременныхТаблиц;

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "
|ВЫБРАТЬ
| Номенклатура, СУММА(Количество) КАК Количество
|ПОМЕСТИТЬ ДокТЧ
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО Номенклатура";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить(); //Прим. 1

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
|ПОМЕСТИТЬ СписокТоваров
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить(); //Прим. 2

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = "
|ВЫБРАТЬ
| Док.Номенклатура,
| Док.Количество КАК Док_Количество,
| ЕСТЬNULL(Рег.КоличествоОстаток,0) КАК Рег_Количество
|ИЗ
| ДокТЧ КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ
|  РегистрНакопления.ОстаткиТоваров.Остатки(,
|  Номенклатура В(ВЫБРАТЬ РАЗЛИЧНЫЕ
|                           Номенклатура
|                          ИЗ
|                           СписокТоваров КАК СписокТоваров)) КАК Рег
| ПО
|  Док.Номенклатура = Рег.Номенклатура";

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

Пока Выборка.Следующий() Цикл

  //Проверка отрицательных остатков

  //Проведение по регистру

КонецЦикла;

КонецПроцедуры


При использовании временных таблиц в тексте запроса применяют инструкцию Поместить для создания новой временной таблицы, в этом случае в результат запроса система передает не содержимое этой таблицы (см прим 1 и прим 2 в тексте выше), а количество записей помещенных во временную таблицу, по желанию можно не принимать это значение.

Также допускается использование инструкции Уничтожить в этом случае временная таблица уничтожается, в противном случае временные таблицы уничтожаются вместе с объектом менеджер временных таблиц.

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

Пакетные запросы

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

В пакетном запросе фактически можно описать несколько запросов, как связанных между собой использованием временных таблиц, так и не связанных (можно, но не понятно зачем?). В итоге можно выполнить последовательно все запросы и принять в результате либо массив с результатами исполнения каждого запроса, либо результат последнего. Для получения массива с результатами запроса применяют метод ВыполнитьПакет() объекта запрос, а для получения результата последнего запроса ВыполнитьЗапрос().

В тексте запроса, запросы пакета разделяются символом «;» (точка с запятой). Область имен виртуальных таблиц у одного пакетного запроса одна. Использование менеджера временных таблиц не требуется, но возможно если вы хотите передать временные таблицы из одного пакетного запроса в другой.

Перепишем процедуру для использования пакетных запросов:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Номенклатура, СУММА(Количество) КАК Количество
|ПОМЕСТИТЬ ДокТЧ
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО Номенклатура
|;
|
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| Номенклатура
|ПОМЕСТИТЬ СписокТоваров
|ИЗ
| Документ.Расходная.Товары
|ГДЕ
| Ссылка = &Ссылка
|;
|
|ВЫБРАТЬ
| Док.Номенклатура,
| Док.Количество КАК Док_Количество,
| ЕСТЬNULL(Рег.КоличествоОстаток,0) КАК Рег_Количество
|ИЗ
| ДокТЧ КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ
|  РегистрНакопления.ОстаткиТоваров.Остатки(,
|  Номенклатура В(ВЫБРАТЬ РАЗЛИЧНЫЕ
|                           Номенклатура
|                          ИЗ
|                           СписокТоваров КАК СписокТоваров)) КАК Рег
| ПО
|  Док.Номенклатура = Рег.Номенклатура";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
МассивРезультаттов = Запрос.ВыполнитьПакет(); //Прим. 1
РезультатЗапроса = Запрос.Выполнить(); //Прим. 2
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл

//Проверка отрицательных остатков

//Проведение по регистру

КонецЦикла;

КонецПроцедуры


Фактически я убрал определение объекта запрос и использование менеджера временных таблиц, объединил тексты запросов (обратите внимание на разделитель «;» между текстами). В результате текст запроса стал читабельнее (а при использовании конструктора запросов намного увеличивается удобство чтения запроса).

После выполнения запроса в переменную МассивРезультатов у нас попадет 3 элемента. Первые два будут содержать число характеризующее количество записей помещенных во временные таблицы ДокТЧ и СписокТоваров, а третий будет содержать выборку с полями Номенклатура, Док_Количество и Рег_Количество.

В переменную РезультатЗапроса попадет только выборка.

Ну вот и все что касается пакетных запросов. Очень удобный механизм и с точки зрения написания запросов и с точки зрения чтения сложных запросов.

Автор: Павел Чистов

Спасибо сказали: Lea, MH.z, mister-x, Trintintin,

Не нашли ответа на свой вопрос?
Зарегистрируйтесь и задайте новый вопрос.


Ответить Новая тема
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

RSS Текстовая версия Сейчас: 28.03.24, 17:38
1С Предприятие 8.3, 1С Предприятие 8.2, 1С Предприятие 8.1, 1С Предприятие 8.0, 1С Предприятие 7.7, Литература 1С, Общие вопросы по администрированию 1С, Методическая поддержка 1С - всё в одном месте: на Украинском 1С форуме!