Часто при разработке отчетов или обработок мы сталкиваемся с необходимостью выбрать данные из нескольких таблиц, связать их и обработать порциями. Разберем подробнее, что на самом деле представляет собой пакетный запрос и как правильно организовать обход результатов, чтобы работать с данными по «партиям» (например, по каждому сотруднику отдельно).
Пакетный запрос — это механизм, позволяющий объединить несколько запросов в одном объекте Запрос. В тексте запроса они разделяются символом точки с запятой (;). Это позволяет выполнять сложные операции поэтапно, используя ВременныеТаблицы. Ваша текущая реализация с ПОМЕСТИТЬ уже является пакетным запросом. Вы создаете промежуточные данные, которые затем соединяете в финальной части. Это отличный способ оптимизации, так как сервер выполняет все вычисления за один проход.
Если вам нужно обработать сначала все документы одного сотрудника, затем другого, использование простого цикла по результату запроса может быть неудобным. Решением здесь выступает использование конструкции ИТОГИ ПО в тексте запроса. Это позволяет платформе автоматически сгруппировать данные по нужному полю.
Рассмотрим пример кода для группировки по сотруднику:
ВЫБРАТЬ
ВТ_Документы.Ссылка КАК Ссылка,
ВТ_Документы.Дата КАК Дата,
Сотрудники.Ссылка КАК ИмяСотрудника
ИЗ
Справочник.Сотрудники КАК Сотрудники
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Документы КАК ВТ_Документы
ПО Сотрудники.Ссылка = ВТ_Документы.ИмяСотрудника
ИТОГИ ПО
ИмяСотрудника
После выполнения запроса важно правильно работать с методом Выбрать. Если вы указали ИТОГИ ПО, вы можете использовать обход ОбходРезультатаЗапроса.ПоГруппировкам. Рассмотрим по шагам, как это реализовать:
Запрос.Выполнить().ОбходРезультатаЗапроса.ПоГруппировкам.Выбрать() для получения детальных записей по каждому конкретному сотруднику.Важно помнить: метод Следующий() должен вызываться со скобками, так как это функция объекта ВыборкаИзРезультатаЗапроса. Посмотрим на пример корректного обхода:
РезультатЗапроса = Запрос.Выполнить();
ВыборкаСотрудник = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "ИмяСотрудника");
Пока ВыборкаСотрудник.Следующий() Цикл
// Здесь мы находимся на уровне конкретного сотрудника
ДетальныеЗаписи = ВыборкаСотрудник.Выбрать();
Пока ДетальныеЗаписи.Следующий() Цикл
// Обрабатываем документы текущего сотрудника
Сообщить("Обработка документа: " + ДетальныеЗаписи.Ссылка);
КонецЦикла;
КонецЦикла;
Хорошей практикой является указание имени группировки во втором параметре метода Выбрать(). Это делает ваш код более читаемым и защищает от ошибок, если в будущем вы решите добавить новые итоги в запрос. Даже если группировка всего одна, привычка именовать их при вызове — это признак качественного стиля программирования.
Если вы столкнулись с необходимостью обработки огромного объема данных, помните, что запрос в цикле (выполнение запроса внутри Пока) — это крайняя мера. Старайтесь делать всё в одном пакетном запросе. Если же документов очень много, и вы боитесь переполнения памяти, используйте пакетные запросы в сочетании с МенеджерВременныхТаблиц. Это позволит удерживать данные во временных таблицах между вызовами методов Выполнить().
Подведем итог:
ИТОГИ ПО в запросе, чтобы разделить выборку на логические части.Следующий().Теперь ваш алгоритм будет работать эффективно, обрабатывая каждого сотрудника и его документы последовательно, не создавая лишней нагрузки на систему.