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