Как работают границы дат в запросах 1С при получении остатков и оборотов?

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

При составлении запросов в 1С разработчики регулярно сталкиваются с вопросом: попадают ли записи, сделанные на граничную дату и время, в результат выборки? Поведение платформы различается в зависимости от того, к какой именно виртуальной таблице происходит обращение и какие конструкторские объекты или операторы применяются. Разберем детально логику обработки границ дат для таблиц остатков, оборотов и оператора МЕЖДУ.

Поведение граничных дат в виртуальной таблице «Остатки»

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

Например, если передать параметр &Дата1 = '31.01.2018 23:59:59' в параметр периода таблицы РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата1, ), то документы и записи, сделанные ровно в 31.01.2018 23:59:59, в результат расчета остатка не попадут.

Для того чтобы включить движения на граничную дату в расчет остатка, используют объект Граница с видом границы ВидГраницы.Включая.


// Передача объекта Граница с включением граничной даты
ГраницаПериода = Новый Граница(КонецДня(Дата1), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Дата1", ГраницаПериода);

Если требуется получить остаток до или после проведения конкретного документа, передают момент времени документа с нужным видом границы:


// Остаток ПОСЛЕ проведения документа (с учетом его собственных движений)
ГраницаПосле = Новый Граница(Ссылка.МоментВремени(), ВидГраницы.Включая);
Запрос.УстановитьПараметр("Период", ГраницаПосле);

Рассмотрим распространенный альтернативный вариант получения остатков на конец дня без использования объекта Граница: прибавление одной секунды к дате. Передавая в параметр периода начало следующего дня (например, 01.02.2018 00:00:00), мы гарантируем, что платформа рассчитает остаток до этой секунды, то есть учтет все записи за 31.01.2018 23:59:59 включительно.


// Альтернатива: смещение на начало следующего дня
Запрос.УстановитьПараметр("Период", КонецДня(Дата1) + 1);

Работа с граничными датами в виртуальной таблице «Обороты»

Выясним, как ведет себя виртуальная таблица Обороты. В отличие от остатков, параметры НачалоПериода и КонецПериода в таблице оборотов работают по правилу полного включения границ по умолчанию.

Передаваемые значения типа Дата и МоментВремени включаются в выборку. Это означает, что при обращении РегистрНакопления.ТоварыНаСкладах.Обороты(&Дата1, &Дата2, Запись, ) записи с временем &Дата1 и &Дата2 полностью попадают в рассчитываемые обороты.

Особенности виртуальной таблицы «Остатки и обороты»

Разберем специфику работы комбинированной виртуальной таблицы ОстаткиИОбороты:

  1. НачалоПериода: начальный остаток рассчитывается исключительно (не включая указанный момент), а обороты за период начинаются включительно (соответствует условию >=).
  2. КонецПериода: по умолчанию включает граничную дату или момент (соответствует условию <=) как для расчета оборотов, так и для расчета конечного остатка.

Использование оператора «МЕЖДУ» в условиях запроса

Посмотрим на применение оператора МЕЖДУ при фильтрации по датам (например, ПланыПродаж.Период МЕЖДУ &Дата1 И &Дата2). Конструкция Поле МЕЖДУ &Дата1 И &Дата2 эквивалентна условию Поле >= &Дата1 И Поле <= &Дата2. Из этого следует, что обе границы берется **включительно**.

Однако при работе с оператором МЕЖДУ важно правильно подготавливать параметры во встроенном языке BSL:

  1. Если в параметр &Дата2 передана дата без времени (например, '20180131'), платформа подставит '31.01.2018 00:00:00'. В результате документы, оформленные в течение дня 31 января, не попадут в условие.
  2. Для корректного отбора за весь период параметр &Дата2 необходимо приводить к концу дня с помощью функции КонецДня().

// Правильная подготовка параметров для оператора МЕЖДУ
Запрос.УстановитьПараметр("Дата1", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("Дата2", КонецДня(ДатаОкончания));

Практические рекомендации и производительность

Проанализируем ключевые особенности применения параметров периода на практике:

  1. Создание объекта Граница: В языке запросов 1С нет конструкторов объектов. Передать объект Граница или МоментВремени в параметр запроса можно только из кода на BSL с помощью метода УстановитьПараметр().
  2. Влияние на производительность: Использование сложных типов параметров (Граница, МоментВремени) в виртуальных таблицах на больших объемах данных может снижать скорость выполнения запроса по сравнению с типом Дата. Это связано с усложнением алгоритмов сопоставления движений и итогов СУБД. В задачах построения отчетов зачастую предпочтительнее передавать сдвинутую дату (КонецДня(Дата) + 1).
← На главную