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