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