Как избежать дублирования записей при расчете итогов по нескольким табличным частям документа

Программист 1С v8.3 (Управляемые формы)
← На главную

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача построения отчета, который должен выводить детальные строки табличных частей документа (например, Номенклатура, Количество) и одновременно показывать общие итоги по всему документу в каждой строке. Типичным примером является документ РеализацияТоваровУслуг, данные в котором распределены по двум основным таблицам: Товары и Услуги. Если подойти к написанию запроса без понимания механизмов работы SQL-соединений, можно столкнуться с проблемой «размножения» (дублирования) строк или неверного расчета сумм, когда в одном документе присутствуют одновременно и товары, и услуги.

В данной статье мы разберем, почему возникает такая ошибка, проанализируем некорректный код и рассмотрим правильный алгоритм построения запроса с использованием временных таблиц.

Разбор типичной ошибки в структуре запроса

Рассмотрим ситуацию, когда разработчик пытается получить общую сумму документа, обращаясь к табличным частям напрямую в основном теле запроса или через некорректные соединения. Проанализируем фрагмент кода, который приводит к ошибкам:


// Фрагмент проблемного запроса
ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Ссылка КАК Ссылка,
    СУММА(РеализацияТоваровУслугТовары.Сумма) КАК Сумма
ПОМЕСТИТЬ СуммаДок
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслугТовары.Ссылка
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    РеализацияТоваровУслугУслуги.Ссылка,
    СУММА(РеализацияТоваровУслугУслуги.Сумма)
ИЗ
    Документ.РеализацияТоваровУслуг.Услуги КАК РеализацияТоваровУслугУслуги
СГРУППИРОВАТЬ ПО
    РеализацияТоваровУслугУслуги.Ссылка

Выясним причину проблемы: В данном примере во временную таблицу СуммаДок попадают две разные записи для одного и того же документа (одна запись с суммой товаров, другая — с суммой услуг). Когда в дальнейшем происходит ЛЕВОЕ СОЕДИНЕНИЕ основной таблицы строк документа с этой временной таблицей по полю Ссылка, система находит два соответствия. В результате каждая строка товара дублируется столько раз, сколько «частей» суммы документа было найдено. Если в документе были и товары, и услуги, количество строк в отчете удвоится, а итоговая сумма будет некорректной.

Правильный алгоритм: Объединение до группировки

Чтобы получить корректную сумму документа, включающую и товары, и услуги, необходимо сначала собрать все значимые суммы в один «плоский» список, и только после этого выполнять агрегацию (группировку). Рассмотрим исправленный подход, который гарантирует уникальность записей по ссылке документа.

Проанализируем шаги реализации:

  1. Создание вложенного запроса: Используем оператор ОБЪЕДИНИТЬ ВСЕ для сбора данных из всех табличных частей без предварительной группировки.
  2. Группировка во временной таблице: На верхнем уровне вложенного запроса выполняем СГРУППИРОВАТЬ ПО полю Ссылка. Это гарантирует, что на один документ будет приходиться ровно одна строка во временной таблице.
  3. Расчет налогов: Внутри группировки учитываем флаг СуммаВключаетНДС, чтобы корректно рассчитать чистую выручку и НДС.

Ниже представлен пример кода, реализующий эту логику:


ВЫБРАТЬ
    т1.Ссылка КАК Ссылка,
    СУММА(т1.СуммаОбщая) КАК Сумма,
    СУММА(т1.СуммаНДС) КАК СуммаНДС,
    СУММА(т1.ЧистаяСумма) КАК БезНДС
ПОМЕСТИТЬ ВТ_ИтогиДокументов
ИЗ
    (ВЫБРАТЬ
        РеализацияТоваровУслугТовары.Ссылка КАК Ссылка,
        ВЫБОР
            КОГДА НЕ РеализацияТоваровУслугТовары.Ссылка.СуммаВключаетНДС
                ТОГДА РеализацияТоваровУслугТовары.Сумма + РеализацияТоваровУслугТовары.СуммаНДС
            ИНАЧЕ РеализацияТоваровУслугТовары.Сумма
        КОНЕЦ КАК СуммаОбщая,
        РеализацияТоваровУслугТовары.СуммаНДС КАК СуммаНДС,
        ВЫБОР
            КОГДА НЕ РеализацияТоваровУслугТовары.Ссылка.СуммаВключаетНДС
                ТОГДА РеализацияТоваровУслугТовары.Сумма
            ИНАЧЕ РеализацияТоваровУслугТовары.Сумма - РеализацияТоваровУслугТовары.СуммаНДС
        КОНЕЦ КАК ЧистаяСумма
    ИЗ
        Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
    ГДЕ
        РеализацияТоваровУслугТовары.Ссылка.Проведен
        И РеализацияТоваровУслугТовары.Ссылка.Дата МЕЖДУ &ДатаНач И &ДатаКон

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ
        РеализацияТоваровУслугУслуги.Ссылка,
        ВЫБОР
            КОГДА НЕ РеализацияТоваровУслугУслуги.Ссылка.СуммаВключаетНДС
                ТОГДА РеализацияТоваровУслугУслуги.Сумма + РеализацияТоваровУслугУслуги.СуммаНДС
            ИНАЧЕ РеализацияТоваровУслугУслуги.Сумма
        КОНЕЦ,
        РеализацияТоваровУслугУслуги.СуммаНДС,
        ВЫБОР
            КОГДА НЕ РеализацияТоваровУслугУслуги.Ссылка.СуммаВключаетНДС
                ТОГДА РеализацияТоваровУслугУслуги.Сумма
            ИНАЧЕ РеализацияТоваровУслугУслуги.Сумма - РеализацияТоваровУслугУслуги.СуммаНДС
        КОНЕЦ
    ИЗ
        Документ.РеализацияТоваровУслуг.Услуги КАК РеализацияТоваровУслугУслуги
    ГДЕ
        РеализацияТоваровУслугУслуги.Ссылка.Проведен
        И РеализацияТоваровУслугУслуги.Ссылка.Дата МЕЖДУ &ДатаНач И &ДатаКон) КАК т1

СГРУППИРОВАТЬ ПО
    т1.Ссылка
ИНДЕКСИРОВАТЬ ПО
    Ссылка
;

Финальное соединение и оптимизация

После того как мы подготовили «чистую» временную таблицу ВТ_ИтогиДокументов, где каждый документ встречается строго один раз, мы можем безопасно соединять ее с исходными данными строк. Обратите внимание на использование инструкции ИНДЕКСИРОВАТЬ ПО. В запросах 1С индексация временных таблиц по полям связи (в данном случае Ссылка) является критически важной для производительности, особенно если документов в выборке больше нескольких сотен.

Важный нюанс: При обращении к реквизитам через точку от ссылки (например, Ссылка.Организация) в секции ГДЕ, платформа 1С создает неявные соединения таблиц. Для оптимизации рекомендуется выбирать необходимые поля шапки (Организация, Контрагент) на этапе формирования временной таблицы, чтобы избежать лишних обращений к базе данных в основном запросе.

Рекомендации по использованию регистров

Проанализируем ситуацию с точки зрения архитектуры крупных систем (ERP, КА, УТ). Запрос напрямую к табличным частям документов считается «тяжелым» и менее эффективным. Рассмотрим альтернативные методы получения данных:

Таким образом, ключ к решению проблемы дублирования записей лежит в правильной последовательности операций: сначала объединение всех источников данных, затем группировка для получения уникальных итогов по документам, и только в конце — соединение с детальными записями отчета.

← На главную