Как правильно получить первый проведенный документ за каждый месяц в 1С?

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

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

Почему фильтрация только по дате — это ошибка?

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

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

Решение проблемы с помощью «Момента времени»

Для однозначной идентификации последовательности событий в 1С используется специальный объект — МоментВремени. Это составной тип данных, который объединяет в себе два поля: Дата и Ссылка. Так как ссылка в базе данных 1С всегда уникальна, использование связки «дата + ссылка» позволяет нам выстроить все документы в строгом порядке, даже если они были проведены в одну и ту же секунду.

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

Пошаговая реализация выбора первого документа

  1. Подготовка периода: Используем функцию НАЧАЛОПЕРИОДА(Документ.Дата, МЕСЯЦ) для приведения всех дат к первому числу месяца.
  2. Группировка: Сгруппируем выборку по полученному периоду.
  3. Поиск минимума: В качестве критерия отбора используем поле МоментВремени.

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


ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(Док.Дата, МЕСЯЦ) КАК Месяц,
    МИНИМУМ(Док.МоментВремени) КАК ПервыйМомент
ИЗ
    Документ.РеализацияТоваровУслуг КАК Док
ГДЕ
    Док.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(Док.Дата, МЕСЯЦ)

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

Альтернативные методы решения

Помимо прямого запроса, задачу можно эффективно решить с помощью Системы Компоновки Данных (СКД):

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

Важное предостережение

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

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

← На главную