Как использовать условие больше или равно (>=) и функцию РАЗНОСТЬДАТ в запросе 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в 1С часто возникает необходимость не просто получить данные из справочников или документов, но и произвести с ними вычисления. Одной из популярных задач является вычисление количества дней, прошедших между двумя датами. Давайте разберем ситуацию, когда нам нужно рассчитать разницу между датой принятия заказа и датой его полной готовности, а затем, в зависимости от того, превышает ли эта разница 6 дней, выполнить определенные действия.

Проанализируем начальные условия. У нас есть запрос, который получает даты из справочника, и нам необходимо задать условие: если разность дат больше или равна 6, то это одна ситуация, а все остальное должно попадать в блок «иначе». Рассмотрим по шагам, как правильно реализовать эту логику с точки зрения синтаксиса языка запросов 1С и последующей обработки результата встроенным языком.

Фильтрация записей с помощью секции ГДЕ

Если наша задача состоит исключительно в том, чтобы оставить в выборке только те строки, где разница между датами составляет 6 или более дней, мы можем использовать секцию ГДЕ. Это самый простой способ отсечь ненужные данные еще на этапе выполнения запроса на сервере базы данных.

Посмотрим на пример такого условия:


ВЫБРАТЬ
    Мойсправочник.ПринятияЗаказа КАК ПринятиеЗаказа,
    Мойсправочник.ПолнаяГотовность КАК ПолнаяГотовность,
    РАЗНОСТЬДАТ(Мойсправочник.ПринятияЗаказа, Мойсправочник.ПолнаяГотовность, ДЕНЬ) КАК РазностьВДнях
ИЗ
    Справочник.Мойсправочник КАК Мойсправочник
ГДЕ
    РАЗНОСТЬДАТ(Мойсправочник.ПринятияЗаказа, Мойсправочник.ПолнаяГотовность, ДЕНЬ) >= 6

Однако этот вариант не подходит, если нам нужны все записи справочника, но для каждой из них нужно установить некий признак или статус в зависимости от срока выполнения заказа.

Использование конструкции ВЫБОР КОГДА в языке запросов

Чтобы реализовать логику «если ... то ... иначе» внутри самого запроса, мы применим специальную конструкцию ВЫБОР. Разберем подробнее её синтаксис. Конструкция позволяет проверить одно или несколько условий и вернуть соответствующий результат в новое поле запроса.

Посмотрим, как будет выглядеть итоговый запрос, который вернет булево значение (Истина или Ложь) в зависимости от того, превышен ли срок в 6 дней:


ВЫБРАТЬ
    Мойсправочник.Ссылка КАК Ссылка,
    Мойсправочник.ПринятияЗаказа КАК ПринятиеЗаказа,
    Мойсправочник.ПолнаяГотовность КАК ПолнаяГотовность,
    ВЫБОР
        КОГДА РАЗНОСТЬДАТ(Мойсправочник.ПринятияЗаказа, Мойсправочник.ПолнаяГотовность, ДЕНЬ) >= 6 
            ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК РазницаБольшеШести
ИЗ
    Справочник.Мойсправочник КАК Мойсправочник

В этом примере мы создали вычисляемое поле РазницаБольшеШести. Система проверит каждую запись: если разница дат больше или равна 6 дням, в это поле будет записано значение ИСТИНА, во всех остальных случаях — ЛОЖЬ.

Обработка результатов запроса и вывод сообщений пользователю

Часто начинающие разработчики пытаются вставить функции встроенного языка, такие как Сообщить(), прямо в текст запроса. Важно понимать: язык запросов 1С работает только с данными базы, он не умеет взаимодействовать с интерфейсом и выводить сообщения пользователю.

Чтобы решить задачу информирования пользователя, мы должны выполнить запрос, получить выборку и обойти ее в цикле с помощью кода на встроенном языке. Разберем по шагам, как это сделать:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Мойсправочник.Ссылка КАК Ссылка,
    |    РАЗНОСТЬДАТ(Мойсправочник.ПринятияЗаказа, Мойсправочник.ПолнаяГотовность, ДЕНЬ) КАК РазностьВДнях
    |ИЗ
    |    Справочник.Мойсправочник КАК Мойсправочник";

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Выполняем проверку условия уже в коде на встроенном языке
    Если Выборка.РазностьВДнях >= 6 Тогда
        Сообщить("Заказ " + Строка(Выборка.Ссылка) + " готовился 6 или более дней!");
    Иначе
        Сообщить("Заказ " + Строка(Выборка.Ссылка) + " уложился в нормативы.");
    КонецЕсли;
КонецЦикла;

В данном скрипте мы получаем точное количество дней из поля РазностьВДнях и уже в модуле проверяем условие через Если ... Тогда ... Иначе. Это наиболее гибкий и правильный подход для вывода текстовых сообщений.

Нюансы использования функции РАЗНОСТЬДАТ

При работе с функцией РАЗНОСТЬДАТ существуют подводные камни, которые могут привести к неверным результатам в отчетах. Проанализируем самые критичные из них:

  1. Отрицательные значения. Функция 1С вычитает первую дату из второй (то есть Формула выглядит как Дата2 - Дата1). Если в вашем справочнике дата «ПринятияЗаказа» по какой-то причине окажется больше (позже), чем дата «ПолнаяГотовность», запрос не выдаст ошибку, а вернет отрицательное число. Соответственно, условие >= 6 не отработает так, как вы ожидали.
  2. Пустые даты. В 1С незаполненная дата представляет собой значение 01.01.0001. Если реквизит ПолнаяГотовность не заполнен, то разница между датой создания документа и пустой датой составит тысячи лет со знаком минус (или плюс, смотря что из чего вычитаем). Чтобы избежать логических ошибок, всегда отсекайте пустые даты в параметрах запроса или проверяйте их через условие ГДЕ Мойсправочник.ПолнаяГотовность <> ДАТАВРЕМЯ(1, 1, 1).
  3. Округление периодов. Если вы передаете параметр ДЕНЬ в функцию, система не высчитывает количество полных 24-часовых интервалов. Она считает количество фактов пересечения полуночи (границы дня). Если заказ принят в 23:55 понедельника, а готов в 00:05 вторника, функция РАЗНОСТЬДАТ вернет значение 1 (один день), хотя по факту прошло всего 10 минут. Если для ваших бизнес-процессов критична точность, вычисляйте разность в часах или секундах с параметрами ЧАС или СЕКУНДА, а затем делите полученное число математически.

Используя приведенные выше конструкции и учитывая особенности работы с датами, вы сможете писать надежные запросы, корректно обрабатывать условия и безошибочно выводить нужную информацию пользователям вашей конфигурации 1С.

← На главную