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