Разработка и Конфигурация · 11 мин
Как найти минимальную дату в 1С
Как найти минимальную дату в 1С: функция МИНИМУМ в запросе, перебор выборки, работа с пустыми датами и NULL. Примеры кода, проверка результата, типичные ошибки.
Задача найти минимальную дату в 1С возникает постоянно: определить первый документ по контрагенту, найти самую раннюю запись в регистре, вычислить дату начала ведения учёта в базе. В зависимости от контекста применяются разные инструменты — агрегатная функция МИНИМУМ в запросе, перебор выборки или таблицы значений, метод Найти для коллекций. Выбор способа влияет и на скорость, и на корректность результата.
Главный подводный камень — пустые даты и значения NULL. Если не обработать их явно, запрос может вернуть 01.01.0001 или NULL вместо ожидаемой «настоящей» даты, а дальнейшие сравнения и расчёты периодов дадут неверные цифры. Поэтому поиск минимальной даты почти всегда идёт в паре с проверкой результата.
Ниже разобраны рабочие способы для языка запросов и встроенного языка 1С, приёмы фильтрации пустых значений, варианты для регистров и документов, а также проверка корректности полученного результата.
Какие способы поиска минимальной даты существуют в 1С
Встроенный язык и язык запросов дают три основных подхода. Первый — агрегатная функция МИНИМУМ() в запросе: платформа вычисляет минимум на стороне СУБД, это самый быстрый вариант для больших таблиц. Второй — перебор выборки из запроса или таблицы значений с ручным сравнением: подходит, когда параллельно с датой нужно получить связанные данные или применить сложную логику. Третий — сортировка с взятием первой строки: используется реже, обычно когда минимум нужен вместе с остальными полями строки.
Для разовых операций в консоли кода или в небольших обработках допустим перебор, но в регламентных заданиях и массовых операциях всегда предпочтителен запрос с МИНИМУМ(): он не выгружает все записи на сервер 1С и не создаёт лишнюю нагрузку.
Сравнение способов
Самый быстрый для больших таблиц; возвращает NULL, если записей нет
Гибкий, позволяет заодно получить связанные поля; медленнее на больших объёмах
Удобен, когда нужна вся строка с минимальной датой; расходует память на сортировку
Как найти минимальную дату запросом через МИНИМУМ
Агрегатная функция МИНИМУМ работает с полями типа «Дата» так же, как с числами: возвращает самое раннее значение среди выбранных записей. Типовой запрос для поиска даты первого документа по контрагенту выглядит так:
ВЫБРАТЬ
МИНИМУМ(РеализацияТоваровУслуг.Дата) КАК ПерваяДата
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Контрагент = &Контрагент
И РеализацияТоваровУслуг.Проведен
Важно понимать поведение функции: если выборка пустая (ни одного документа не найдено), МИНИМУМ вернёт NULL, а не пустую дату. Если в таблице есть записи с незаполненной датой, в минимум попадёт 01.01.0001. Оба случая нужно обрабатывать в коде после выполнения запроса.
Минимальная дата с группировкой
Если нужна минимальная дата по каждому объекту — например, первая продажа по каждому контрагенту — добавьте группировку. Поле, по которому группируете, указывается в СГРУППИРОВАТЬ ПО, а МИНИМУМ считается внутри каждой группы:
ВЫБРАТЬ
РеализацияТоваровУслуг.Контрагент КАК Контрагент,
МИНИМУМ(РеализацияТоваровУслуг.Дата) КАК ПерваяПродажа
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Проведен
СГРУППИРОВАТЬ ПО
РеализацияТоваровУслуг.Контрагент
Как найти минимальную дату перебором в коде
Когда данные уже находятся в таблице значений или массиве, запрос не нужен — достаточно простого цикла со сравнением. Начальное значение удобно задать как заведомо большую дату или как Неопределено с проверкой на первой итерации:
МинимальнаяДата = Неопределено;
Для Каждого Строка Из ТаблицаДокументов Цикл
Если Не ЗначениеЗаполнено(Строка.Дата) Тогда
Продолжить;
КонецЕсли;
Если МинимальнаяДата = Неопределено
Или Строка.Дата < МинимальнаяДата Тогда
МинимальнаяДата = Строка.Дата;
КонецЕсли;
КонецЦикла;
Такой подход даёт полный контроль: можно пропускать пустые даты, учитывать дополнительные условия (только проведённые, только по конкретному складу) и сразу запоминать ссылку на строку или документ с минимальной датой. Плата за гибкость — скорость: перебор миллиона записей в коде заметно медленнее запроса.
Минимальная дата вместе со ссылкой на документ
Частая задача — найти не просто дату, а самый ранний документ целиком. Здесь удобна сортировка в запросе с ограничением выборки:
ВЫБРАТЬ ПЕРВЫЕ 1
РеализацияТоваровУслуг.Ссылка КАК Документ,
РеализацияТоваровУслуг.Дата КАК Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ГДЕ
РеализацияТоваровУслуг.Контрагент = &Контрагент
И РеализацияТоваровУслуг.Проведен
УПОРЯДОЧИТЬ ПО
Дата
Конструкция «ПЕРВЫЕ 1» с упорядочиванием по возрастанию даты вернёт самый ранний документ. Учтите нюанс: у документов, созданных в одну секунду, порядок определяется также ссылкой, поэтому при равных датах результат может отличаться от ожиданий — для строгого порядка добавьте в сортировку дополнительное поле.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ МИНИМУМ(Док.Дата) КАК ПерваяДата ИЗ Документ.РеализацияТоваровУслуг КАК Док ГДЕ Док.Проведен";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() И Выборка.ПерваяДата <> NULL Тогда
Сообщить("Первая дата: " + Формат(Выборка.ПерваяДата, "ДЛФ=D"));
Иначе
Сообщить("Документы не найдены");
КонецЕсли;Как обработать пустые даты и NULL
Пустая дата в 1С — это 01.01.0001 00:00:00, и формально она меньше любой реальной даты. Если в данных встречаются незаполненные даты (например, в регистре сведений или в реквизите «Дата окончания»), МИНИМУМ честно вернёт 01.01.0001. Чтобы исключить такие значения, добавьте условие в запрос:
ГДЕ
Таблица.Дата > ДАТАВРЕМЯ(1, 1, 1)
Обратная ситуация — когда запрос вообще ничего не вернул. Тогда поле результата содержит NULL, и любое сравнение или вычитание дат с NULL даст NULL либо ошибку приведения типов. Надёжный шаблон проверки в коде: сначала проверить, что выборка не пустая и значение не NULL, затем — что дата заполнена функцией ЗначениеЗаполнено(). Только после этого использовать дату в расчётах.
Минимальная дата в регистрах: накопления и сведений
В регистрах накопления и сведений дата хранится в поле «Период», и поиск минимума строится аналогично — МИНИМУМ(Регистр.Период). Для виртуальных таблиц (например, «Остатки») минимум по периоду не имеет смысла: там период задаётся параметром. Работайте с физической таблицей регистра, а не с виртуальной.
Для регистров сведений с режимом «Подчинение регистратору» период совпадает с датой документа-регистратора, поэтому дополнительно фильтруйте по типу регистратора, если записи пишутся разными документами. Для независимых периодических регистров сведений минимальный период покажет, с какого момента вообще ведётся история по объекту — это удобный способ проверить полноту данных.
- 1Определите, где искать: документ, регистр, таблица значений в памяти
- 2Напишите запрос с МИНИМУМ() и отбором по нужным условиям (проведён, контрагент, период)
- 3Исключите пустые даты условием Дата > ДАТАВРЕМЯ(1,1,1), если они возможны в данных
- 4Выполните запрос и проверьте результат: выборка не пустая, значение не NULL, ЗначениеЗаполнено() = Истина
- 5Только после проверок используйте дату в расчётах, отчётах или движениях
Как проверить, что дата найдена правильно
Простой способ верификации — сравнить результат МИНИМУМ с ручной проверкой через список. Откройте журнал документов с тем же отбором, отсортируйте по дате по возрастанию и сверьте первую запись с результатом запроса. Даты должны совпасть с точностью до секунды.
Второй признак корректности — поведение при пустых данных. Временно задайте отбор, который заведомо ничего не вернёт (несуществующий контрагент): код должен отработать без ошибок и сообщить об отсутствии данных, а не упасть на сравнении с NULL. Если при пустой выборке возникает ошибка — обработка NULL написана неверно.
Как проверить результат
Дата из запроса совпадает с датой первого документа в отсортированном списке
Даты расходятся — проверьте отборы и флаг Проведен
Код сообщает об отсутствии данных без ошибок
Ошибка приведения типов или сравнения с NULL
В результат попадает реальная рабочая дата
Получено 01.01.0001 — нужен фильтр ДАТАВРЕМЯ(1,1,1)
Типичные ошибки при поиске минимальной даты
Самая распространённая ошибка — забыть про NULL и сразу использовать результат в вычислениях: РазностьДат(МинДата, ТекущаяДата) с NULL-первым аргументом даёт NULL, который «молча» уходит дальше по алгоритму и портит отчёт. Вторая частая ошибка — не отфильтровать непроведённые или помеченные на удаление документы: минимальная дата находится по черновику, которого в учёте нет.
Третья группа ошибок связана с составом даты. Поле «Дата» документа содержит время, и сравнение с датой без времени (началом дня) может дать неожиданные результаты: документ от 10:30:00 не равен дате 00:00:00 того же дня. Для сравнений по дню используйте НАЧАЛОПЕРИОДА() в запросе или НачалоДня() в коде.
В типовых конфигурациях минимальную дату часто ищут для установки даты запрета изменения данных. Перед изменением этой настройки выгрузите список документов раньше найденной даты и согласуйте с учётными службами — закрытие периода с незавершёнными документами создаёт проблемы при сверках.
Частые вопросы
Что вернёт МИНИМУМ, если записей нет?
NULL. Поэтому после выполнения запроса проверяйте, что выборка не пустая и значение поля не равно NULL, прежде чем использовать его в сравнениях и расчётах.
Как найти минимальную дату без времени, только день?
Примените функцию НАЧАЛОПЕРИОДА(Таблица.Дата, ДЕНЬ) внутри МИНИМУМ в запросе либо НачалоДня() при переборе в коде. Тогда результатом будет 00:00:00 соответствующего дня.
Почему минимальная дата получилась 01.01.0001?
В выборку попали записи с незаполненной датой — она меньше любой реальной. Добавьте в запрос условие Дата > ДАТАВРЕМЯ(1, 1, 1) или отсекайте пустые значения проверкой ЗначениеЗаполнено() при переборе.
Как найти самый ранний документ, а не только его дату?
Используйте запрос с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1 и упорядочиванием по полю Дата по возрастанию. В выборку включите ссылку на документ и другие нужные поля.
Что быстрее: МИНИМУМ в запросе или перебор таблицы значений?
Для данных в базе — МИНИМУМ в запросе: вычисление выполняется на СУБД без передачи всех записей. Перебор оправдан, только если данные уже загружены в таблицу значений в памяти или нужна сложная логика отбора.
Как найти минимальную дату по нескольким видам документов сразу?
Объедините таблицы через ОБЪЕДИНИТЬ ВСЕ во вложенном запросе, выбрав из каждой поле даты, а затем примените МИНИМУМ к объединённому результату. Альтернатива — журнал документов, если нужные виды в него включены.
Что важно запомнить
Минимальную дату в 1С надёжнее всего искать функцией МИНИМУМ() в запросе. Всегда обрабатывайте два особых случая: NULL при пустой выборке и 01.01.0001 при незаполненных датах. Если нужен сам документ, а не только дата — используйте ПЕРВЫЕ 1 с сортировкой по дате. Результат проверяйте сверкой с отсортированным списком перед использованием в расчётах.