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

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с проблемой «двоения» или «множения» строк. Это происходит, когда в одном запросе мы пытаемся соединить левым соединением несколько табличных частей одного документа. Например, если в документе ОтчетПроизводстваЗаСмену в табличной части «Продукция» 5 строк, а в табличной части «Исполнители» — 3 строки, то при обычном левом соединении по ссылке мы получим 15 строк (произведение количеств). Это классическая проблема декартова произведения.

Разберем подробно несколько эффективных способов решения этой задачи: от оптимизации текста запроса до использования встроенных функций агрегации СКД и программной обработки.

Способ 1. Использование объединения (UNION ALL) вместо соединений

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

Рассмотрим пример запроса, который решает проблему дублей:


ВЫБРАТЬ
    ОтчетПроизводстваЗаСменуПродукция.Ссылка КАК Ссылка,
    ОтчетПроизводстваЗаСменуПродукция.Номенклатура КАК Номенклатура,
    СУММА(ОтчетПроизводстваЗаСменуПродукция.Количество) КАК Количество,
    NULL КАК Сотрудник
ИЗ
    Документ.ОтчетПроизводстваЗаСмену.Продукция КАК ОтчетПроизводстваЗаСменуПродукция
СГРУППИРОВАТЬ ПО
    ОтчетПроизводстваЗаСменуПродукция.Ссылка,
    ОтчетПроизводстваЗаСменуПродукция.Номенклатура

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

ВЫБРАТЬ
    ОтчетПроизводстваЗаСменуИсполнители.Ссылка,
    NULL,
    NULL,
    ОтчетПроизводстваЗаСменуИсполнители.Сотрудник
ИЗ
    Документ.ОтчетПроизводстваЗаСмену.Исполнители КАК ОтчетПроизводстваЗаСменуИсполнители

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

Способ 2. Использование нескольких наборов данных и связей

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

  1. Создадим НаборДанных1 (Объект или Запрос), который выбирает только шапки документов (поле Ссылка).
  2. Создадим НаборДанных2 для табличной части «Продукция».
  3. Создадим НаборДанных3 для табличной части «Исполнители».
  4. Перейдем на закладку Связи наборов данных.

Настроим связи: НаборДанных1 будет источником связи, а остальные наборы — приемниками. Поле связи — Ссылка. В этом случае СКД выполнит запросы последовательно и соединит их на этапе компоновки результата, полностью исключая дублирование записей. Вы сможете вывести продукцию и исполнителей в параллельных группировках или даже в одной строке, используя ресурсы.

Способ 3. Вывод данных табличной части в одну ячейку через ресурсы

Часто заказчик просит не плодить строки вниз, а перечислить, например, всех исполнителей в одной ячейке через запятую. Для этого в СКД предусмотрены мощные функции агрегации. Выясним, как использовать функцию СоединитьСтроки.

На закладке Ресурсы для поля Сотрудник напишем выражение:

СоединитьСтроки(Массив(Сотрудник), ", ")

Проанализируем, что здесь происходит: функция Массив() собирает все уникальные значения сотрудников в рамках текущей группировки, а СоединитьСтроки() склеивает их в одну текстовую строку с указанным разделителем. Это позволяет сделать отчет максимально компактным.

Также можно использовать более сложные функции для работы с коллекциями непосредственно в схеме:

Способ 4. Программная обработка данных при выводе

Если стандартных средств СКД недостаточно или требуется сложная логика формирования строки (например, в обычном приложении или при ручном обходе результата), можно воспользоваться перебором массива в коде 1С. Рассмотрим ситуацию, когда мы получили массив данных и нам нужно вывести его в параметр области макета.


ПеременнаяРезультат = "";
Для Инд = 0 По МойМассив.ВГраница() Цикл
    ПеременнаяРезультат = ПеременнаяРезультат + Строка(МойМассив[Инд]) + "; " + Символы.ПС;
КонецЦикла;
Область.Параметры.ПолеВывода = ПеременнаяРезультат;

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

СУММА(ЕстьNull(Количество, 0))

Резюме

Для эффективной настройки отчета в СКД с несколькими табличными частями придерживайтесь следующих правил:

  1. Если нужно просто вывести списки без сложной иерархии — используйте ОБЪЕДИНИТЬ ВСЕ с NULL значениями.
  2. Если отчет сложный и многоуровневый — используйте связи нескольких наборов данных.
  3. Для компактного отображения данных табличных частей в строке используйте ресурс СоединитьСтроки.
  4. Всегда следите за ролями полей на соответствующей закладке СКД, чтобы система понимала, какие поля являются измерениями, а какие — детальными записями.

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

← На главную