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

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

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

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

Задача найти минимальную дату возникает в запросах 1С постоянно: определить первую продажу клиенту, дату первого документа по контрагенту, самое раннее движение по регистру или начало действия цены. Язык запросов 1С предлагает для этого несколько инструментов, и выбор правильного зависит от того, откуда берутся данные — из таблицы документов, периодического регистра сведений или результата соединения нескольких таблиц.

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

Функция МИНИМУМ: базовый способ получить самую раннюю дату

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

ВЫБРАТЬ

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

МИНИМУМ(Продажи.Период) КАК ПерваяПродажа

ИЗ

РегистрНакопления.Продажи КАК Продажи

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

Продажи.Контрагент

Запрос вернёт по каждому контрагенту дату его первой продажи. Если группировка не нужна и требуется одна минимальная дата по всей таблице, секцию СГРУППИРОВАТЬ ПО просто опускают — тогда результатом будет одна строка.

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

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

Частая ситуация: нужна не просто первая дата, а полный документ — ссылка, номер, сумма. Конструкция ВЫБРАТЬ ПЕРВЫЕ 1 в сочетании с упорядочиванием решает эту задачу напрямую.

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

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

Реализация.Дата КАК Дата,

Реализация.СуммаДокумента КАК Сумма

ИЗ

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

ГДЕ

Реализация.Контрагент = &Контрагент

И Реализация.Проведен

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

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

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

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

Порядок действий для записи с минимальной датой
  1. 1
    Определите, нужна одна запись по всей таблице или по каждой группе
  2. 2
    Для одной записи используйте ВЫБРАТЬ ПЕРВЫЕ 1 с УПОРЯДОЧИТЬ ПО Дата
  3. 3
    Добавьте условия отбора: проведённые документы, нужный период, организация
  4. 4
    Для групп постройте вложенный запрос с МИНИМУМ и соедините его с исходной таблицей
  5. 5
    Проверьте результат на данных, где возможны совпадающие даты внутри группы

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

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

ВЫБРАТЬ

Срез.Номенклатура КАК Номенклатура,

Срез.Период КАК ДатаУстановки,

Срез.Цена КАК Цена

ИЗ

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

&Период,

ТипЦен = &ТипЦен) КАК Срез

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

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

Сравнение способов выбора минимальной даты

МИНИМУМ с группировкой

Универсально для любых таблиц, но возвращает только дату; для остальных полей нужно дополнительное соединение

ПЕРВЫЕ 1 с упорядочиванием

Даёт всю запись целиком, но работает для одной группы за раз; для множества групп неудобен

СрезПервых

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

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

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

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

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

МИНИМУМ(Товары.Период) КАК ДатаПервогоДвижения

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Товары

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

Товары.Номенклатура

Если регистр большой, обязательно накладывайте отборы до группировки — по складу, организации или диапазону дат. Группировка по полной таблице движений за несколько лет может выполняться десятки секунд и блокировать работу пользователей в файловой базе.

Проверка результата и контроль корректности

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

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

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

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

Дата первой операции по контрольному объекту
Норма

Совпадает с датой первого проведённого документа в базе

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

Дата раньше реальной — попали непроведённые или помеченные документы

Количество строк в результате
Норма

Одна строка на каждую группу

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

Несколько строк на группу — совпадающие минимальные даты дали дубли

Группы без данных
Норма

NULL или отсутствие строки обработано в коде

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

Пустая дата интерпретируется как реальная и попадает в отчёт

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

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

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

Третья ошибка — использование МИНИМУМ над результатом соединения без учёта размножения строк. Если к документу присоединена табличная часть, каждая строка документа дублируется, и хотя сама минимальная дата не исказится, связанные агрегаты (суммы, количества) будут завышены.

Типичные ошибки
01
Вывод полей вне группировки рядом с МИНИМУМ — в результат попадают значения из произвольных строк
02
Отсутствие отбора по проведённым документам — первой оказывается дата черновика
03
Соединение по паре группа+дата без учёта совпадающих дат — задвоение строк и завышение сумм
04
Игнорирование NULL в пустых группах — пустая дата уходит дальше в отчёт как реальная
05
Группировка по полному регистру без отборов — запрос выполняется минутами и блокирует базу

FAQ: частые вопросы о выборе минимальной даты

Чем МИНИМУМ отличается от СрезПервых?

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

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

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

Почему МИНИМУМ вернул NULL, хотя записи есть?

Функция игнорирует NULL, но если все значения в группе равны NULL — например, после левого соединения по группе без совпадений — результатом будет NULL. Обработайте этот случай через ЕСТЬNULL(Поле, ДатаПоУмолчанию) или проверку в коде.

Как учесть время, а не только календарную дату?

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

Что делать, если у нескольких записей одинаковая минимальная дата?

Определите дополнительный критерий уникальности — например, минимальную ссылку или номер документа — и добавьте его во вложенный запрос. Иначе соединение по дате вернёт все совпадающие записи и размножит строки результата.

Работает ли СрезПервых для регистров накопления?

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

Итог

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

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