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