При разработке отчетов и обработок в платформе 1С часто возникает задача сворачивания таблицы с договорами: необходимо для каждого контрагента оставить ровно одну запись. Рассмотрим несколько способов решения этой задачи в зависимости от условий: когда подойдет любой договор, когда нужен определенный основной договор или когда требуется выбрать наиболее актуальный договор по дате.
Разберем самый простой вариант. Если бизнес-логика не требует конкретного договора, а достаточно получить любой один договор на контрагента, мы можем сгруппировать записи по владельцу и применить функцию МАКСИМУМ или МИНИМУМ к полю ссылки на договор.
Проанализируем пример запроса к справочнику договоров:
ВЫБРАТЬ
ДоговорыКонтрагентов.Владелец КАК Контрагент,
МАКСИМУМ(ДоговорыКонтрагентов.Ссылка) КАК Договор
ИЗ
Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
ГДЕ
ДоговорыКонтрагентов.Ссылка В(&МассивДоговоров)
ГРУППИРОВАТЬ ПО
ДоговорыКонтрагентов.Владелец
Важное замечание: Функция МАКСИМУМ по полю типа Ссылка выполняется на уровне СУБД путем бинарного сравнения внутренних уникальных идентификаторов (GUID). Это гарантирует получение ровно одного договора для каждого контрагента, однако не гарантирует конкретный хронологический порядок создания элемента.
Рассмотрим ситуацию, когда в конфигурации у контрагента зафиксирован основной договор в соответствующем реквизите ОсновнойДоговорКонтрагента. В таком случае нет необходимости выбирать список всех договоров и группировать их — достаточно обратиться к самому контрагенту.
Посмотрим на пример запроса:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
Контрагенты.ОсновнойДоговорКонтрагента КАК Договор
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
НЕ Контрагенты.ОсновнойДоговорКонтрагента ЕСТЬ NULL
И НЕ Контрагенты.ОсновнойДоговорКонтрагента = ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка)
Этот способ оптимален по производительности, так как запрос выбирает готовую ссылку без применения агрегации и сложных соединений.
Выясним, как поступить, если требуется получить не произвольный договор, а самый свежий (по дате или номеру). В языке запросов 1С отсутствуют оконные функции, поэтому задачу решают с помощью пакета запросов и временных таблиц.
Разберем процесс поэтапно:
ВТ_МаксДаты.Рассмотрим пример построения такого пакета запросов:
// Запрос 1: Получение максимальной даты договора для каждого контрагента
ВЫБРАТЬ
Договоры.Владелец КАК Контрагент,
МАКСИМУМ(Договоры.Дата) КАК МаксДата
ПОМЕСТИТЬ ВТ_МаксДаты
ИЗ
Справочник.ДоговорыКонтрагентов КАК Договоры
ГРУППИРОВАТЬ ПО
Договоры.Владелец
;
////////////////////////////////////////////////////////////////////////////////
// Запрос 2: Получение одного договора по найденной дате
ВЫБРАТЬ
ВТ_МаксДаты.Контрагент КАК Контрагент,
МАКСИМУМ(Договоры.Ссылка) КАК Договор
ИЗ
ВТ_МаксДаты КАК ВТ_МаксДаты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК Договоры
ПО ВТ_МаксДаты.Контрагент = Договоры.Владелец
И ВТ_МаксДаты.МаксДата = Договоры.Дата
ГРУППИРОВАТЬ ПО
ВТ_МаксДаты.Контрагент
Рекомендация по производительности: При работе с большими объемами данных во временных таблицах всегда используйте предложение ИНДЕКСИРОВАТЬ ПО для полей соединения (Контрагент, Дата), чтобы избежать снижения скорости выполнения запроса СУБД.