При разработке сложных отчетов или обработок на платформе 1С программисты часто сталкиваются с необходимостью производить вычисления над датами непосредственно в запросе. Одной из самых коварных ошибок является сообщение «Неверные параметры в запросе», возникающее при использовании функции ДОБАВИТЬКДАТЕ. Давайте детально разберем, почему возникает эта проблема, и как правильно выстроить логику запроса, чтобы избежать ошибок типизации.
Проанализируем типичную ситуацию, представленную в исходном коде. Программист пытается вычислить, истек ли срок годности партии товара, используя следующий фрагмент во втором запросе пакета:
| ДОБАВИТЬКДАТЕ(ВремТаб.СрокГ, СЕКУНДА, ВремТаб.НачИстекЛиСрок) КАК ИстекЛиСрок
Выясним причину сбоя. Функция ДОБАВИТЬКДАТЕ имеет строго определенную структуру и ожидает параметры конкретных типов:
Дата.Число.В приведенном примере поле ВремТаб.СрокГ было получено в первом запросе путем умножения: ПартииОстатки.Номенклатура.СрокГодности * &ДеньВСекундах. Результатом такой операции всегда является Число. Попытка подставить числовое значение в первый аргумент функции, где ожидается дата, и приводит к ошибке «Неверные параметры».
Рассмотрим правильный подход. Вместо того чтобы пытаться складывать два числа через функцию даты, нам нужно прибавлять срок (число) к реальной дате (поле типа дата). Пересмотрим структуру формирования временной таблицы. Нам целесообразно сразу получить дату окончания срока годности в первом запросе.
Предположим, что срок годности в справочнике Номенклатура хранится в днях. Тогда правильный текст первого запроса будет выглядеть так:
"ВЫБРАТЬ
| ПартииОстатки.ДатаИзготовления КАК ДатаИзготовления,
| ПартииОстатки.Номенклатура.СрокГодности КАК СрокВДнях,
| ДОБАВИТЬКДАТЕ(ПартииОстатки.ДатаИзготовления, ДЕНЬ, ПартииОстатки.Номенклатура.СрокГодности) КАК ДатаИстечения
|ПОМЕСТИТЬ ВремТаб
|ИЗ
| РегистрНакопления.Партии.Остатки КАК ПартииОстатки"
В этом случае во втором запросе нам не придется производить сложные вычисления — мы просто сможем сравнить поле ДатаИстечения с текущей датой или использовать его для вывода в отчет.
Проанализируем ситуацию, когда пользователь в сообщении №8 пишет, что простое сложение ВремТаб.СрокГ + ВремТаб.НачИстекЛиСрок не выдает ошибку. Это происходит потому, что оба поля являются числами, и язык запросов 1С позволяет выполнять арифметические операции между числовыми полями. Однако, важно понимать: результатом будет число, а не дата.
Если ваша задача — просто получить какой-то числовой коэффициент или разницу в секундах, этот метод допустим. Но если вы хотите получить дату, к которой можно применить формат или использовать в календаре, такой способ бесполезен.
Зачастую вычисления с датами нужны только для того, чтобы наложить фильтр (например, выбрать просроченные товары). Рассмотрим, как сделать это максимально эффективно. Вместо того чтобы вычислять новую колонку, мы можем использовать условие в секции ГДЕ.
Допустим, нам нужно найти все товары, срок годности которых истек на текущую дату &ТекДата. Проанализируем два варианта:
Вариант А (менее эффективный):
ГДЕ
РАЗНОСТЬДАТ(ПартииОстатки.ДатаИзготовления, &ТекДата, ДЕНЬ) > ПартииОстатки.Номенклатура.СрокГодности
Вариант Б (рекомендуемый):
ГДЕ
ДОБАВИТЬКДАТЕ(ПартииОстатки.ДатаИзготовления, ДЕНЬ, ПартииОстатки.Номенклатура.СрокГодности) < &ТекДата
Второй вариант работает быстрее на больших объемах данных, так как функция ДОБАВИТЬКДАТЕ лучше оптимизируется СУБД при работе с индексами по полю даты.
Разберем еще несколько моментов, которые могут вызвать скрытые ошибки:
NULL. Всегда используйте ЕСТЬNULL(ПолеДата, ДАТАВРЕМЯ(1, 1, 1)), если не уверены в заполненности данных.ВЫРАЗИТЬ(ВашеЧисло КАК ЧИСЛО(15, 0)). Дробное число в параметре количества также приведет к ошибке неверных параметров.Подводя итог, можно сказать: всегда четко контролируйте типы данных в ваших временных таблицах. Если вы используете ДОБАВИТЬКДАТЕ, убедитесь, что первый аргумент — это именно поле типа Дата, а не результат арифметических вычислений, превративший его в число.