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

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

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

Разберем причину возникновения дублей при группировке

Проанализируем типичную ошибку. Когда мы пишем запрос и добавляем в него поле Менеджер, а затем пытаемся сгруппировать результат по номеру заявки и выбрать МАКСИМУМ(ДатаСогласования), система 1С требует, чтобы поле Менеджер также было включено в секцию СГРУППИРОВАТЬ ПО.

Как только мы добавляем текстовое поле в группировку, СУБД начинает искать уникальные комбинации всех указанных полей. Если для одной заявки сначала был назначен «Иванов», а затем «Петров», то для системы это две разные уникальные записи: «Заявка №1 + Иванов» и «Заявка №1 + Петров». В итоге группировка не схлопывает эти строки, и мы получаем две записи на одну заявку, каждая со своей датой. Наша же цель — получить только одну строку с «Петровым», так как его дата согласования была позже.

Решение проблемы с помощью временных таблиц

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

Шаг 1: Получение максимальных дат во временную таблицу

Создадим первый запрос, в котором выберем только идентификатор объекта (например, Ссылка или НомерЗаявки) и максимальную дату. Результат поместим во временную таблицу ВТ_МаксимальныеДаты.


ВЫБРАТЬ
    Заявка.Ссылка КАК Ссылка,
    МАКСИМУМ(Заявка.ДатаСогласования) КАК МаксДата
ПОМЕСТИТЬ ВТ_МаксимальныеДаты
ИЗ
    Документ.Заявка КАК Заявка
СГРУППИРОВАТЬ ПО
    Заявка.Ссылка
;

Шаг 2: Соединение временной таблицы с исходными данными

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


ВЫБРАТЬ
    ВТ.Ссылка,
    ВТ.МаксДата,
    ИсходнаяТаблица.Менеджер КАК ПоследнийМенеджер
ИЗ
    ВТ_МаксимальныеДаты КАК ВТ
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.Заявка КАК ИсходнаяТаблица
        ПО ВТ.Ссылка = ИсходнаяТаблица.Ссылка
            И ВТ.МаксДата = ИсходнаяТаблица.ДатаСогласования

Как быть, если даты совпадают?

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

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

Посмотрим на пример с использованием номера строки:


ВЫБРАТЬ
    Ссылка КАК Ссылка,
    МАКСИМУМ(НомерСтроки) КАК МаксНомер
ПОМЕСТИТЬ ВТ_ПоследниеСтроки
ИЗ
    Документ.Заявка.Менеджеры
ГДЕ
    Менеджер <> ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)
СГРУППИРОВАТЬ ПО
    Ссылка
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ТЧ.Ссылка,
    ТЧ.Менеджер
ИЗ
    ВТ_ПоследниеСтроки КАК ВТ
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Заявка.Менеджеры КАК ТЧ
        ПО ВТ.Ссылка = ТЧ.Ссылка
            И ВТ.МаксНомер = ТЧ.НомерСтроки

Обратите внимание на условие Менеджер <> ЗНАЧЕНИЕ(...). Оно крайне важно, если в системе могут быть «пустые» записи о назначениях. Это гарантирует, что мы найдем последнего заполненного менеджера, а не просто последнюю созданную запись.

Особенности работы с задачами бизнес-процессов

Если ваша задача связана с бизнес-процессами (точками маршрута), как упоминалось в обсуждении, помните о реквизите ДатаИсполнения. В отличие от даты создания задачи, именно ДатаИсполнения (или ДатаЗавершения) определяет, когда менеджер фактически выполнил свою работу на точке маршрута. При построении запроса по задачам рекомендуется фильтровать записи по состоянию Выполнена = ИСТИНА, чтобы отчет не подтянул текущего исполнителя, который еще не принял решение, вместо последнего фактически согласовавшего сотрудника.

Использование Среза Последних для регистров сведений

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

Запрос будет выглядеть максимально просто:


ВЫБРАТЬ
    Регистр.Заявка,
    Регистр.Менеджер
ИЗ
    РегистрСведений.ИсторияМенеджеров.СрезПоследних(&Период, ) КАК Регистр

Система сама оптимизирует выполнение этого запроса на уровне СУБД, выбирая только актуальные записи на указанный момент времени по каждому измерению регистра.

Резюме

Для получения последнего текстового значения в запросе 1С придерживайтесь следующих правил:

  1. Никогда не добавляйте текстовое поле (менеджера) в группировку, если вам нужно свернуть строки по объекту.
  2. Используйте временные таблицы для предварительного поиска максимального значения даты или номера строки.
  3. При соединении таблиц всегда используйте комбинированный ключ (Ссылка + МаксимальноеПоле), чтобы избежать дублей при совпадении дат.
  4. Если данные позволяют, переведите хранение информации в регистр сведений, чтобы использовать механизм виртуальных таблиц СрезПоследних.

Такой структурный подход не только решит проблему с дубликатами, но и сделает ваш код более понятным и быстрым для SQL-сервера.

← На главную