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