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