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