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

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

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

Анализ причины проблемы

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

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


ВЫБРАТЬ
	ДокументЗаказПокупателя.Ссылка КАК ЗаказПокупателя,
	ДокументЗаказПокупателя.Ссылка.СуммаДокумента КАК СуммаДокумента,
	ДокументЗаказПокупателя.Номенклатура КАК Номенклатура,
	...
ПОМЕСТИТЬ ВР
ИЗ
	Документ.ЗаказПокупателя.Запасы КАК ДокументЗаказПокупателя
		ЛЕВОЕ СОЕДИНЕНИЕ ...

Именно из-за этого соединения поле СуммаДокумента будет повторяться для каждой Номенклатура одного и того же заказа. Задача — показать СуммаДокумента один раз для всего документа.

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

Решение 1: Настройка структуры и ресурсов в СКД (Рекомендуемый способ)

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

Шаг 1. Настройка ресурсов

Ресурсы в СКД — это поля, для которых необходимо рассчитать итоги (сумму, количество, среднее, максимум и т.д.).

  1. Откройте схему компоновки данных и перейдите на вкладку "Ресурсы".
  2. Добавьте новые строки для полей, которые дублируются. В нашем случае это СуммаДокумента и Процент.
  3. В колонке "Выражение" для этих полей укажите агрегатную функцию. Поскольку значение суммы документа одинаково для всех строк одного документа, можно использовать Максимум(СуммаДокумента), Минимум(СуммаДокумента) или Среднее(СуммаДокумента). Результат будет одинаковым — система возьмет одно из повторяющихся значений. Чаще всего используют Максимум().

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

Шаг 2. Настройка структуры отчета

Теперь нужно правильно выстроить иерархию в отчете.

  1. Перейдите на вкладку "Настройки".
  2. Создайте новую группировку. В качестве поля группировки выберите ссылку на документ — ЗаказПокупателя.
  3. В секции "Выбранные поля" для этой группировки перетащите поля, относящиеся к шапке документа (Номер, Дата, Контрагент), а также наши настроенные ресурсы (СуммаДокумента, Процент).
  4. Теперь внутрь этой группировки добавьте вложенную группировку. Это могут быть "Детальные записи" или группировка по полю Номенклатура.
  5. В "Выбранные поля" для детальных записей перетащите поля из табличной части (Номенклатура, Объем, Цена и т.д.).

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

Решение 2: Использование агрегатных функций и группировки в запросе

Этот способ заключается в изменении самого текста запроса. Он менее гибкий, так как агрегация данных происходит на уровне СУБД, и СКД получает уже сгруппированный набор данных. Однако его тоже полезно знать.

Автор в теме попытался использовать этот метод, но допустил ошибку, которая привела к сообщению "Поле не входит в группу". Разберем, как сделать правильно.

Правило использования СГРУППИРОВАТЬ ПО:

Если в секции ВЫБРАТЬ запроса используется хотя бы одна агрегатная функция (МАКСИМУМ, СУММА, КОЛИЧЕСТВО и т.п.), то все остальные поля из секции ВЫБРАТЬ, которые не обернуты в агрегатные функции, должны быть перечислены в секции СГРУППИРОВАТЬ ПО.

Автор в сообщении 10 попытался сделать так:


...
СГРУППИРОВАТЬ ПО
    СуммаДокумента,
    Процент

Это неверно, так как он пытается сгруппировать данные по полям, к которым уже применена агрегатная функция. Нужно группировать по всем остальным полям, которые определяют уникальность строки.

Исправленный вариант запроса:

Чтобы исправить запрос, нужно добавить МАКСИМУМ() к нужным полям и перечислить все остальные поля в секции СГРУППИРОВАТЬ ПО.


ВЫБРАТЬ
	ДокументЗаказПокупателя.Ссылка КАК ЗаказПокупателя,
	ДокументЗаказПокупателя.Ссылка.ПометкаУдаления КАК ПометкаУдаления,
	ДокументЗаказПокупателя.Ссылка.Номер КАК Номер,
	ДокументЗаказПокупателя.Ссылка.Дата КАК Дата,
	ДокументЗаказПокупателя.Ссылка.Проведен КАК Проведен,
	ДокументЗаказПокупателя.Ссылка.ДатаОтгрузки КАК ДатаОтгрузки,
	ДокументЗаказПокупателя.Ссылка.Комментарий КАК Комментарий,
	ДокументЗаказПокупателя.Ссылка.Контрагент КАК Контрагент,
	ДокументЗаказПокупателя.Ссылка.Ответственный КАК Ответственный,
	ДокументЗаказПокупателя.Ссылка.СостояниеЗаказа КАК СостояниеЗаказа,
	МАКСИМУМ(ДокументЗаказПокупателя.Ссылка.СуммаДокумента) КАК СуммаДокумента,
	ДокументЗаказПокупателя.Ссылка.ЖелтушникВОфисе КАК ЖелтушникВОфисе,
	ДокументЗаказПокупателя.Ссылка.СуммаДоставки КАК СтоимостьДоставки,
	ВЫРАЗИТЬ(ДокументЗаказПокупателяДоставкаУПДВходТовары.УПДвходТовар КАК СТРОКА(30)) КАК УПДвходТовар,
	ВЫРАЗИТЬ(ДокументЗаказПокупателяДоставкаУПДВходУслуги.УПДвходУслуги КАК СТРОКА(30)) КАК УПДвходУслуги,
	ЗаказПокупателяДополнительныеРеквизиты.Значение КАК УПДВход,
	ДокументЗаказПокупателя.Номенклатура КАК Номенклатура,
	ЗаказПокупателяДоставка.Объем КАК Объем,
	ЗаказПокупателяДоставка.Цена КАК Цена,
	ЗаказПокупателяДоставка.Перевозка КАК Перевозка,
	ЗаказПокупателяДоставка.КоличествоРейсов КАК КоличествоРейсов,
	МАКСИМУМ(ЗаказПокупателя.Процент.Процент) КАК Процент,
	ЗаказПокупателя.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВР
ИЗ
	Документ.ЗаказПокупателя.Запасы КАК ДокументЗаказПокупателя
	...
СГРУППИРОВАТЬ ПО
	ДокументЗаказПокупателя.Ссылка,
	ДокументЗаказПокупателя.Ссылка.ПометкаУдаления,
	ДокументЗаказПокупателя.Ссылка.Номер,
	ДокументЗаказПокупателя.Ссылка.Дата,
	ДокументЗаказПокупателя.Ссылка.Проведен,
	ДокументЗаказПокупателя.Ссылка.ДатаОтгрузки,
	ДокументЗаказПокупателя.Ссылка.Комментарий,
	ДокументЗаказПокупателя.Ссылка.Контрагент,
	ДокументЗаказПокупателя.Ссылка.Ответственный,
	ДокументЗаказПокупателя.Ссылка.СостояниеЗаказа,
	ДокументЗаказПокупателя.Ссылка.ЖелтушникВОфисе,
	ДокументЗаказПокупателя.Ссылка.СуммаДоставки,
	ВЫРАЗИТЬ(ДокументЗаказПокупателяДоставкаУПДВходТовары.УПДвходТовар КАК СТРОКА(30)),
	ВЫРАЗИТЬ(ДокументЗаказПокупателяДоставкаУПДВходУслуги.УПДвходУслуги КАК СТРОКА(30)),
	ЗаказПокупателяДополнительныеРеквизиты.Значение,
	ДокументЗаказПокупателя.Номенклатура,
	ЗаказПокупателяДоставка.Объем,
	ЗаказПокупателяДоставка.Цена,
	ЗаказПокупателяДоставка.Перевозка,
	ЗаказПокупателяДоставка.КоличествоРейсов,
	ЗаказПокупателя.Ссылка

Как видите, секция СГРУППИРОВАТЬ ПО становится очень громоздкой. Этот подход работает, но усложняет чтение и поддержку запроса.

Решение 3: Использование нескольких наборов данных (Продвинутый способ)

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

  1. Набор данных "Шапки": Создайте первый набор данных, который выбирает информацию только из шапки документа.
    
    ВЫБРАТЬ
        ЗаказПокупателя.Ссылка КАК ЗаказПокупателя,
        ЗаказПокупателя.Дата,
        ЗаказПокупателя.Номер,
        ЗаказПокупателя.Контрагент,
        ЗаказПокупателя.СуммаДокумента,
        ЗаказПокупателя.Процент.Процент КАК Процент
    ИЗ
        Документ.ЗаказПокупателя КАК ЗаказПокупателя
    
  2. Набор данных "Товары": Создайте второй набор данных для табличной части "Запасы".
    
    ВЫБРАТЬ
        ЗаказПокупателяЗапасы.Ссылка КАК ЗаказПокупателя,
        ЗаказПокупателяЗапасы.Номенклатура,
        ЗаказПокупателяЗапасы.Количество,
        ЗаказПокупателяЗапасы.Цена,
        ЗаказПокупателяЗапасы.Сумма
    ИЗ
        Документ.ЗаказПокупателя.Запасы КАК ЗаказПокупателяЗапасы
    
  3. Связь наборов данных: Перейдите на вкладку "Связи наборов данных". Создайте новую связь. Укажите, что первый набор (Шапки) является источником, а второй (Товары) — приемником. Свяжите их по общему полю ЗаказПокупателя (типа ДокументСсылка.ЗаказПокупателя).

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

Итог: Для решения проблемы дублирования данных шапки документа в отчетах СКД самым простым и предпочтительным методом является настройка ресурсов и структуры отчета (Решение 1). Он не требует изменения запроса и использует все возможности компоновки данных. Для более сложных и высоконагруженных отчетов рекомендуется использовать несколько наборов данных (Решение 3) для оптимизации производительности и чистоты кода.

← На главную