К статье
Практический материал

Разработка и Конфигурация · 10 мин

1С запрос: дата как период — приёмы работы и примеры

Как в запросе 1С использовать дату как период: НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА, ПЕРИОДАМИ, параметры виртуальных таблиц. Примеры кода и типичные ошибки.

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

Практическая задача возникает постоянно: отобрать документы за месяц, сгруппировать продажи по неделям, получить остатки на конец дня, сравнить дату документа с периодом записи регистра сведений. Для каждого сценария в языке запросов есть свой инструмент — функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА, конструкция ПЕРИОДАМИ, параметры виртуальных таблиц регистров.

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

Чем дата отличается от периода в запросе

Тип «Дата» в 1С содержит календарную дату и время с точностью до секунды. Сравнение двух дат — это сравнение моментов времени: условие Документ.Дата = &Дата выполнится только при совпадении до секунды, что почти никогда не нужно в прикладных задачах.

Период — это именованный интервал: день, неделя, декада, месяц, квартал, полугодие, год. Когда пользователь выбирает в отчёте «за март», система должна интерпретировать это как диапазон от 00:00:00 первого числа до 23:59:59 последнего. Преобразование даты в границы такого диапазона и есть суть приёма «дата как период».

Функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА

Основной инструмент — пара функций, возвращающих границы периода, в который попадает дата. Синтаксис: НАЧАЛОПЕРИОДА(<Дата>, <Периодичность>) и КОНЕЦПЕРИОДА(<Дата>, <Периодичность>). Например, НАЧАЛОПЕРИОДА(&Дата, МЕСЯЦ) вернёт первое число месяца в 00:00:00, а КОНЕЦПЕРИОДА(&Дата, МЕСЯЦ) — последнее число в 23:59:59.

Типовой пример — отбор документов за месяц, в который попадает произвольная дата параметра:

ВЫБРАТЬ

Реализация.Ссылка,

Реализация.Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

ГДЕ

Реализация.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, МЕСЯЦ)

И КОНЕЦПЕРИОДА(&Дата, МЕСЯЦ)

Функции применимы и к полям выборки, а не только к параметрам. Например, можно вывести начало недели для каждого документа и затем сгруппировать по этому полю — так строят помесячные и понедельные отчёты без дополнительных вычислений на встроенном языке.

Группировка данных по периодам

Для агрегатных отчётов дату приводят к началу периода и группируют по полученному значению. Так суммы продаж, обороты склада или количество документов сворачиваются в месячные или квартальные итоги:

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) КАК Месяц,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты(, , Регистратор, ) КАК Продажи

СГРУППИРОВАТЬ ПО

НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ)

УПОРЯДОЧИТЬ ПО

Месяц

Важный нюанс: сортировку тоже выполняют по вычисленному полю периода, иначе строки выводятся в произвольном порядке. Если отчёт строится через СКД, ту же задачу решает поле-период в настройках компоновки — но на уровне текста запроса приём с НАЧАЛОПЕРИОДА остаётся универсальным.

Конструкция ПЕРИОДАМИ для итогов

Когда нужны итоги с нарастающей детализацией — год, внутри него кварталы, внутри месяцы — используется секция ИТОГИ ... ПЕРИОДАМИ. Она автоматически формирует группировочные записи по каждому уровню периодичности без ручного вычисления границ:

ВЫБРАТЬ

Продажи.Период КАК Период,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты(, , Месяц, ) КАК Продажи

ИТОГИ

СУММА(Сумма)

ПО

Период ПЕРИОДАМИ(МЕСЯЦ, &НачалоПериода, &КонецПериода)

Особенность конструкции: при указании границ &НачалоПериода и &КонецПериода в результат попадут и пустые периоды без данных — с нулевыми итогами. Это удобно для графиков и сводных таблиц, где пропуск месяца ломает ось времени, но требует аккуратной обработки пустых строк при программном обходе выборки.

Дата как период в виртуальных таблицах регистров

Регистры сведений с режимом «в пределах периода» и регистры накопления предоставляют виртуальные таблицы, где границы периода передаются параметрами: СрезПервых, СрезПоследних, Остатки, Обороты, ОстаткиИОбороты. Параметр периода здесь — обычная дата, но трактуется она как граница интервала.

Пример получения цен на конец дня указанной даты:

ВЫБРАТЬ

Цены.Номенклатура,

Цены.Цена

ИЗ

РегистрСведений.ЦеныНоменклатуры.СрезПоследних(

КОНЕЦПЕРИОДА(&Дата, ДЕНЬ), ) КАК Цены

Тонкость в том, какое значение передавать. Для СрезПоследних момент включается в выборку, поэтому передача КОНЕЦПЕРИОДА(&Дата, ДЕНЬ) захватывает записи, сделанные в течение дня. Для Оборотов параметры задают начало и конец интервала, и снова корректная пара — НАЧАЛОПЕРИОДА для старта и КОНЕЦПЕРИОДА для завершения.

Порядок действий
  1. 1
    Определите, какой интервал нужен: день, месяц, квартал или произвольный диапазон
  2. 2
    Вычислите границы функциями НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА с нужной периодичностью
  3. 3
    Передайте границы в условие ГДЕ или в параметры виртуальной таблицы
  4. 4
    Выполните запрос в консоли запросов и сверьте, что документы на границах периода попали в выборку
  5. 5
    Проверьте время выполнения на реальном объёме данных

Проверка результата и типичные ошибки

Контрольный признак корректного запроса — поведение на границах интервала. Документ от 00:00:00 первого числа должен попадать в выборку, документ от 23:59:59 последнего числа — тоже, а документ следующего дня — нет. Проверяйте это в консоли запросов на тестовых данных до переноса текста в модуль.

Самая частая ошибка — сравнение даты документа с параметром-датой на равенство, когда пользователь вводит дату без времени (00:00:00). В результате за день попадают только документы, проведённые ровно в полночь. Вторая типичная ошибка — использование функции ДАТАВРЕМЯ с жёстко заданными границами там, где период должен вычисляться из параметра.

Типичные ошибки
01
Сравнение Дата = &Дата вместо диапазона МЕЖДУ НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА — из выборки выпадают все документы, кроме проведённых в 00:00:00
02
Передача в СрезПоследних начала дня вместо конца — записи, созданные в течение дня, не учитываются
03
Вычисление границ периода в цикле на встроенном языке вместо одной функции в запросе — лишний код и потеря производительности
04
ИТОГИ ПЕРИОДАМИ без указания границ на незаполненных данных — в результате нет пустых периодов, и отчёт выглядит непоследовательным
Контрольные точки

Как проверить результат

Документ на границе периода
Норма

Документ от 00:00:00 первого дня и от 23:59:59 последнего дня присутствуют в выборке

Тревожный признак

Пограничные документы отсутствуют — границы вычислены неверно

Срез последних на дату
Норма

Возвращается актуальное значение с учётом записей внутри дня

Тревожный признак

Возвращается вчерашнее значение — передано начало дня вместо конца

Время выполнения
Норма

Запрос отрабатывает за приемлемое время на рабочем объёме

Тревожный признак

Запрос зависает — проверьте индексы и уберите ИТОГИ ПЕРИОДАМИ

Альтернативы и выбор подхода

Не всегда преобразование нужно делать в тексте запроса. Если границы периода известны заранее (например, из настроек отчёта), их вычисляют один раз на встроенном языке — функциями НачалоМесяца(), КонецМесяца() и аналогами — и передают в запрос готовыми параметрами. Это упрощает текст запроса и позволяет повторно использовать те же значения в нескольких запросах пакета.

В системе компоновки данных периодичность группировки задаётся настройками отчёта, а поля-периоды (День, Месяц, Квартал) платформа формирует автоматически для виртуальных таблиц оборотов. Ручное вычисление через НАЧАЛОПЕРИОДА в СКД обычно требуется только для нестандартных интервалов вроде декад или произвольных производственных недель.

Сравнение вариантов

НАЧАЛОПЕРИОДА/КОНЕЦПЕРИОДА в запросе

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

Параметры, вычисленные на встроенном языке

Быстрее и чище текст запроса; подходит, когда границы известны до выполнения, но не работает для вычислений по полям выборки

ИТОГИ ПЕРИОДАМИ

Даёт многоуровневые итоги и пустые периоды без ручного кода; ограничение — нагрузка на больших таблицах

Поля-периоды СКД

Самый простой путь для отчётов на компоновке; не подходит для обычных запросов в модулях

FAQ

Как получить все документы за день, если в параметре только дата без времени?

Оберните параметр в границы дня: условие Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата, ДЕНЬ). Тогда в выборку попадут документы с любым временем внутри суток, а не только проведённые в 00:00:00.

Чем отличается периодичность НЕДЕЛЯ от ДЕКАДА в НАЧАЛОПЕРИОДА?

НЕДЕЛЯ приводит дату к понедельнику соответствующей календарной недели. ДЕКАДА делит месяц на три интервала: с 1 по 10, с 11 по 20 и с 21 по конец месяца. Для отчётов по производственным декадам используется именно ДЕКАДА, неделей её заменить нельзя.

Почему СрезПоследних на дату возвращает устаревшее значение?

Чаще всего в параметр передано начало дня (дата с временем 00:00:00), поэтому записи, сделанные позже в тот же день, не учитываются. Передайте КОНЕЦПЕРИОДА(&Дата, ДЕНЬ) — момент конца дня включается в срез.

Можно ли использовать НАЧАЛОПЕРИОДА в секции СГРУППИРОВАТЬ ПО?

Да, функция допустима в группировке, и это стандартный приём для помесячных и поквартальных итогов. Выражение в СГРУППИРОВАТЬ ПО должно совпадать с выражением в списке выборки, а сортировку лучше выполнять по тому же вычисленному полю.

Что выбрать для границы периода: КОНЕЦПЕРИОДА или вычитание секунды из начала следующего дня?

Используйте КОНЕЦПЕРИОДА — функция возвращает корректную последнюю секунду интервала и читается в тексте запроса однозначно. Ручная арифметика с секундами чувствительна к ошибкам и усложняет сопровождение кода.

Работает ли ПЕРИОДАМИ в запросах к обычным таблицам документов, а не к виртуальным таблицам регистров?

Да, конструкция ИТОГИ ПЕРИОДАМИ применима к любому полю типа Дата в выборке, включая дату документа. При указании параметров границ в результат попадут и периоды без документов — с пустыми значениями итогов.

Итог

Что важно запомнить

Дата превращается в период функциями НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА с указанием периодичности; для многоуровневых итогов служит ИТОГИ ПЕРИОДАМИ, а в виртуальных таблицах регистров границы передаются параметрами. Всегда проверяйте запрос на границах интервала — именно там скрываются типичные ошибки отбора.