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

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

Как найти минимальную дату в 1С

Как найти минимальную дату в 1С: функция МИНИМУМ в запросе, перебор выборки, работа с пустыми датами и NULL. Примеры кода, проверка результата, типичные ошибки.

Задача найти минимальную дату в 1С возникает постоянно: определить первый документ по контрагенту, найти самую раннюю запись в регистре, вычислить дату начала ведения учёта в базе. В зависимости от контекста применяются разные инструменты — агрегатная функция МИНИМУМ в запросе, перебор выборки или таблицы значений, метод Найти для коллекций. Выбор способа влияет и на скорость, и на корректность результата.

Главный подводный камень — пустые даты и значения NULL. Если не обработать их явно, запрос может вернуть 01.01.0001 или NULL вместо ожидаемой «настоящей» даты, а дальнейшие сравнения и расчёты периодов дадут неверные цифры. Поэтому поиск минимальной даты почти всегда идёт в паре с проверкой результата.

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

Какие способы поиска минимальной даты существуют в 1С

Встроенный язык и язык запросов дают три основных подхода. Первый — агрегатная функция МИНИМУМ() в запросе: платформа вычисляет минимум на стороне СУБД, это самый быстрый вариант для больших таблиц. Второй — перебор выборки из запроса или таблицы значений с ручным сравнением: подходит, когда параллельно с датой нужно получить связанные данные или применить сложную логику. Третий — сортировка с взятием первой строки: используется реже, обычно когда минимум нужен вместе с остальными полями строки.

Для разовых операций в консоли кода или в небольших обработках допустим перебор, но в регламентных заданиях и массовых операциях всегда предпочтителен запрос с МИНИМУМ(): он не выгружает все записи на сервер 1С и не создаёт лишнюю нагрузку.

Сравнение способов

МИНИМУМ() в запросе

Самый быстрый для больших таблиц; возвращает NULL, если записей нет

Перебор выборки со сравнением

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

Сортировка и первая строка

Удобен, когда нужна вся строка с минимальной датой; расходует память на сортировку

Как найти минимальную дату запросом через МИНИМУМ

Агрегатная функция МИНИМУМ работает с полями типа «Дата» так же, как с числами: возвращает самое раннее значение среди выбранных записей. Типовой запрос для поиска даты первого документа по контрагенту выглядит так:

ВЫБРАТЬ

МИНИМУМ(РеализацияТоваровУслуг.Дата) КАК ПерваяДата

ИЗ

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

ГДЕ

РеализацияТоваровУслуг.Контрагент = &Контрагент

И РеализацияТоваровУслуг.Проведен

Важно понимать поведение функции: если выборка пустая (ни одного документа не найдено), МИНИМУМ вернёт NULL, а не пустую дату. Если в таблице есть записи с незаполненной датой, в минимум попадёт 01.01.0001. Оба случая нужно обрабатывать в коде после выполнения запроса.

Минимальная дата с группировкой

Если нужна минимальная дата по каждому объекту — например, первая продажа по каждому контрагенту — добавьте группировку. Поле, по которому группируете, указывается в СГРУППИРОВАТЬ ПО, а МИНИМУМ считается внутри каждой группы:

ВЫБРАТЬ

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

МИНИМУМ(РеализацияТоваровУслуг.Дата) КАК ПерваяПродажа

ИЗ

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

ГДЕ

РеализацияТоваровУслуг.Проведен

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

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

Как найти минимальную дату перебором в коде

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

МинимальнаяДата = Неопределено;

Для Каждого Строка Из ТаблицаДокументов Цикл

Если Не ЗначениеЗаполнено(Строка.Дата) Тогда

Продолжить;

КонецЕсли;

Если МинимальнаяДата = Неопределено

Или Строка.Дата < МинимальнаяДата Тогда

МинимальнаяДата = Строка.Дата;

КонецЕсли;

КонецЦикла;

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

Минимальная дата вместе со ссылкой на документ

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

ВЫБРАТЬ ПЕРВЫЕ 1

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

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

ИЗ

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

ГДЕ

РеализацияТоваровУслуг.Контрагент = &Контрагент

И РеализацияТоваровУслуг.Проведен

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

Дата

Конструкция «ПЕРВЫЕ 1» с упорядочиванием по возрастанию даты вернёт самый ранний документ. Учтите нюанс: у документов, созданных в одну секунду, порядок определяется также ссылкой, поэтому при равных датах результат может отличаться от ожиданий — для строгого порядка добавьте в сортировку дополнительное поле.

bsl
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ МИНИМУМ(Док.Дата) КАК ПерваяДата ИЗ Документ.РеализацияТоваровУслуг КАК Док ГДЕ Док.Проведен";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() И Выборка.ПерваяДата <> NULL Тогда
	Сообщить("Первая дата: " + Формат(Выборка.ПерваяДата, "ДЛФ=D"));
Иначе
	Сообщить("Документы не найдены");
КонецЕсли;

Как обработать пустые даты и NULL

Пустая дата в 1С — это 01.01.0001 00:00:00, и формально она меньше любой реальной даты. Если в данных встречаются незаполненные даты (например, в регистре сведений или в реквизите «Дата окончания»), МИНИМУМ честно вернёт 01.01.0001. Чтобы исключить такие значения, добавьте условие в запрос:

ГДЕ

Таблица.Дата > ДАТАВРЕМЯ(1, 1, 1)

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

Минимальная дата в регистрах: накопления и сведений

В регистрах накопления и сведений дата хранится в поле «Период», и поиск минимума строится аналогично — МИНИМУМ(Регистр.Период). Для виртуальных таблиц (например, «Остатки») минимум по периоду не имеет смысла: там период задаётся параметром. Работайте с физической таблицей регистра, а не с виртуальной.

Для регистров сведений с режимом «Подчинение регистратору» период совпадает с датой документа-регистратора, поэтому дополнительно фильтруйте по типу регистратора, если записи пишутся разными документами. Для независимых периодических регистров сведений минимальный период покажет, с какого момента вообще ведётся история по объекту — это удобный способ проверить полноту данных.

Порядок действий
  1. 1
    Определите, где искать: документ, регистр, таблица значений в памяти
  2. 2
    Напишите запрос с МИНИМУМ() и отбором по нужным условиям (проведён, контрагент, период)
  3. 3
    Исключите пустые даты условием Дата > ДАТАВРЕМЯ(1,1,1), если они возможны в данных
  4. 4
    Выполните запрос и проверьте результат: выборка не пустая, значение не NULL, ЗначениеЗаполнено() = Истина
  5. 5
    Только после проверок используйте дату в расчётах, отчётах или движениях

Как проверить, что дата найдена правильно

Простой способ верификации — сравнить результат МИНИМУМ с ручной проверкой через список. Откройте журнал документов с тем же отбором, отсортируйте по дате по возрастанию и сверьте первую запись с результатом запроса. Даты должны совпасть с точностью до секунды.

Второй признак корректности — поведение при пустых данных. Временно задайте отбор, который заведомо ничего не вернёт (несуществующий контрагент): код должен отработать без ошибок и сообщить об отсутствии данных, а не упасть на сравнении с NULL. Если при пустой выборке возникает ошибка — обработка NULL написана неверно.

Контрольные точки

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

Сверка с журналом
Норма

Дата из запроса совпадает с датой первого документа в отсортированном списке

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

Даты расходятся — проверьте отборы и флаг Проведен

Пустой результат
Норма

Код сообщает об отсутствии данных без ошибок

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

Ошибка приведения типов или сравнения с NULL

Пустые даты в данных
Норма

В результат попадает реальная рабочая дата

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

Получено 01.01.0001 — нужен фильтр ДАТАВРЕМЯ(1,1,1)

Типичные ошибки при поиске минимальной даты

Самая распространённая ошибка — забыть про NULL и сразу использовать результат в вычислениях: РазностьДат(МинДата, ТекущаяДата) с NULL-первым аргументом даёт NULL, который «молча» уходит дальше по алгоритму и портит отчёт. Вторая частая ошибка — не отфильтровать непроведённые или помеченные на удаление документы: минимальная дата находится по черновику, которого в учёте нет.

Третья группа ошибок связана с составом даты. Поле «Дата» документа содержит время, и сравнение с датой без времени (началом дня) может дать неожиданные результаты: документ от 10:30:00 не равен дате 00:00:00 того же дня. Для сравнений по дню используйте НАЧАЛОПЕРИОДА() в запросе или НачалоДня() в коде.

Типичные ошибки
01
Не проверять NULL: расчёты периодов молча дают пустой или неверный результат
02
Не исключать пустые даты: минимумом становится 01.01.0001 вместо реальной даты
03
Игнорировать пометку удаления: минимум находится по документу, исключённому из учёта
04
Сравнивать даты со временем без приведения к началу дня: условие равенства не срабатывает
05
Перебирать миллионы записей в коде вместо МИНИМУМ() в запросе: лишняя нагрузка на сервер
В типовых конфигурациях минимальную дату часто ищут для установки даты запрета изменения данных. Перед изменением этой настройки выгрузите список документов раньше найденной даты и согласуйте с учётными службами — закрытие периода с незавершёнными документами создаёт проблемы при сверках.
ПЗ
Практическое замечание

Частые вопросы

Что вернёт МИНИМУМ, если записей нет?

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

Как найти минимальную дату без времени, только день?

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

Почему минимальная дата получилась 01.01.0001?

В выборку попали записи с незаполненной датой — она меньше любой реальной. Добавьте в запрос условие Дата > ДАТАВРЕМЯ(1, 1, 1) или отсекайте пустые значения проверкой ЗначениеЗаполнено() при переборе.

Как найти самый ранний документ, а не только его дату?

Используйте запрос с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1 и упорядочиванием по полю Дата по возрастанию. В выборку включите ссылку на документ и другие нужные поля.

Что быстрее: МИНИМУМ в запросе или перебор таблицы значений?

Для данных в базе — МИНИМУМ в запросе: вычисление выполняется на СУБД без передачи всех записей. Перебор оправдан, только если данные уже загружены в таблицу значений в памяти или нужна сложная логика отбора.

Как найти минимальную дату по нескольким видам документов сразу?

Объедините таблицы через ОБЪЕДИНИТЬ ВСЕ во вложенном запросе, выбрав из каждой поле даты, а затем примените МИНИМУМ к объединённому результату. Альтернатива — журнал документов, если нужные виды в него включены.

Итог

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

Минимальную дату в 1С надёжнее всего искать функцией МИНИМУМ() в запросе. Всегда обрабатывайте два особых случая: NULL при пустой выборке и 01.01.0001 при незаполненных датах. Если нужен сам документ, а не только дата — используйте ПЕРВЫЕ 1 с сортировкой по дате. Результат проверяйте сверкой с отсортированным списком перед использованием в расчётах.