Как правильно соединить табличные части документов в отчете СКД, чтобы суммы не дублировались?

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

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

В этой статье мы подробно разберем, почему возникает эта ошибка, как правильно перестроить запрос и какие инструменты СКД помогут получить корректный результат.

Разбор основной проблемы: Декартово произведение

Выясним причину, по которой данные в отчете могут отображаться некорректно. Когда мы соединяем две таблицы (в нашем случае — табличные части двух документов) по номенклатуре, СУБД ищет все совпадения. Если в документе-основании одна и та же Номенклатура встречается в двух разных строках, то каждая строка из документа перемещения будет продублирована дважды. В итоге при расчете ресурсов в СКД (сумм и количеств) значения будут складываться столько раз, сколько соответствий нашлось во второй таблице.

Проанализируем ситуацию на примере. Если в перемещении 10 штук товара, а в наряде-основании этот товар разбит на две строки по 5 штук (например, с разными характеристиками или сериями, которые не указаны в связи), то в отчете может появиться строка с количеством 20 или две строки по 10. Это классическая проблема неточного соединения таблиц.

Шаг 1: Отказ от вложенных таблиц в пользу плоских

Рассмотрим распространенную ошибку в написании запроса. Часто разработчики используют конструктор, который генерирует выборку через точку от шапки документа, например: Перемещение.Товары.(Номенклатура, Количество). Для СКД такой подход крайне нежелателен, так как он создает выборку во вложенной таблице, которой сложно управлять при связях.

Вместо этого мы должны обращаться напрямую к таблице табличной части. Посмотрим на правильную структуру обращения к данным:


ВЫБРАТЬ
    ПеремещениеТовары.Ссылка КАК ДокументПеремещения,
    ПеремещениеТовары.Номенклатура КАК Номенклатура,
    ПеремещениеТовары.Количество КАК Количество,
    ПеремещениеТовары.РозничнаяЦена КАК РозничнаяЦена,
    НарядБлюда.ПриходнаяЦена КАК ПриходнаяЦена,
    ЕСТЬNULL(НарядБлюда.ПриходнаяСумма, 0) КАК ПриходнаяСумма
ИЗ
    Документ.Перемещение.Товары КАК ПеремещениеТовары
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.НарядНаПроизводство.Блюда КАК НарядБлюда
        ПО ПеремещениеТовары.Ссылка.ДокументОснование = НарядБлюда.Ссылка
            И ПеремещениеТовары.Номенклатура = НарядБлюда.Номенклатура

Обратите внимание: мы выбираем данные из Документ.Перемещение.Товары. Это позволяет работать с каждой строкой документа как с отдельной записью, что критично для правильной работы СКД.

Шаг 2: Правильная настройка условий соединения

Разберем подробнее условия связи в предложении ПО. Чтобы избежать дублирования, связь должна быть максимально жесткой. В нашем случае мы связываем таблицы по двум полям:

  1. Документ-основание: Мы проверяем, что ссылка в шапке перемещения совпадает со ссылкой в таблице блюд наряда.
  2. Номенклатура: Мы сопоставляем конкретные товары.

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

Шаг 3: Обращение к реквизитам шапки и проблема «точек»

Часто возникает вопрос: как обращаться к дате документа или складу, если мы выбираем данные из табличной части? Правильный способ — использовать обращение через поле Ссылка. Рассмотрим пример:

ПеремещениеТовары.Ссылка.Дата или ПеремещениеТовары.Ссылка.СкладОтправитель.

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

Шаг 4: Использование связей наборов данных в СКД

В СКД есть альтернативный и зачастую более надежный способ решения проблемы — использование двух отдельных наборов данных. Рассмотрим этот метод:

  1. Набор данных 1 (Запрос): Выбирает данные только из перемещения (Товары, Количество, Розничные цены).
  2. Набор данных 2 (Запрос): Выбирает данные только из наряда на производство (Номенклатура, Приходные цены).
  3. Связи наборов данных: На специальной вкладке в СКД настраиваем связь. Поле источника — ДокументОснование и Номенклатура, поле приемника — Ссылка и Номенклатура.

Этот метод хорош тем, что СКД сама оптимизирует передачу параметров и корректно вычисляет итоги по ресурсам, минимизируя риск получения «раздутых» сумм.

Шаг 5: Работа с неопределенными значениями (NULL)

Выясним еще одну деталь: при левом соединении, если в документе-основании не найдется подходящей номенклатуры, поля цен и сумм будут содержать NULL. Это может привести к тому, что итоги в отчете не будут считаться вовсе. Всегда используйте функцию ЕСТЬNULL в запросе, чтобы заменить пустоту на ноль:

ЕСТЬNULL(НарядБлюда.ПриходнаяЦена, 0) КАК ПриходнаяЦена

Итоги и рекомендации

Подведем итог нашему разбору. Для создания надежного отчета в СКД при соединении документов придерживайтесь следующих правил:

  1. Всегда работайте с плоскими таблицами табличных частей (.Товары, .Состав и т.д.).
  2. Настраивайте связи явно в запросе или через механизмы связей наборов данных СКД.
  3. Если в документе-основании данные могут дублироваться, используйте вложенные запросы с группировкой.
  4. Следите за ролями полей на закладке «Наборы данных»: поля ресурсов должны иметь тип агрегации «Сумма», а ключевые поля (Номенклатура, Ссылка) — быть измерениями.
  5. Хотя в ряде задач требуется обращение к документам, помните: отчеты по регистрам накопления всегда работают быстрее и стабильнее в долгосрочной перспективе.

Соблюдение этих принципов позволит вам создавать корректные отчеты, которые будут выдавать правильные цифры независимо от сложности структуры документов.

← На главную