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

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

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

Почему использование нескольких наборов данных — это крайний случай

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

Золотое правило разработки СКД: если данные можно получить одним запросом (используя соединения или объединения), следует использовать именно один запрос. Это упрощает настройку ресурсов, отборов и связей. Рассмотрим подробнее, как преобразовать разрозненные наборы в один эффективный запрос.

Разбор ошибки 1: Направление связи и типы данных

Если вы все же решили использовать связи наборов данных, обратите внимание на сообщение 8 и сообщение 23. Важно, какой набор является "ведущим". Если вам нужно вывести всех клиентов, даже тех, по которым не было продаж, ведущим набором должен быть список клиентов. К нему мы "левым соединением" привязываем данные о продажах.

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

Разбор ошибки 2: Отсутствие поля в Ресурсах

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

Любое числовое поле (Сумма, Количество), которое должно выводиться на пересечении группировок, обязано быть добавлено в список ресурсов. Рассмотрим, как это сделать правильно:

  1. Перейдите на закладку Ресурсы.
  2. Перенесите поле Сумма в правую колонку.
  3. Убедитесь, что в колонке "Выражение" указано СУММА(Сумма).
  4. В колонке "Рассчитывать по..." оставьте пустое значение, если итог нужен по всем группировкам, или укажите конкретные измерения.

Правильный подход: Использование одного набора данных (Запрос)

Чтобы избежать путаницы со связями, объединим данные о клиентах, складах и продажах в одном запросе. Мы будем использовать ЛЕВОЕ СОЕДИНЕНИЕ, чтобы гарантировать вывод всех необходимых клиентов, и обязательно сгруппируем данные на уровне запроса, чтобы не передавать в СКД лишние строки. Посмотрим на пример оптимизированного запроса:


ВЫБРАТЬ
    Партнеры.Ссылка КАК Клиент,
    СкладыКлиентов.Ссылка КАК СкладКлиента,
    ЕСТЬNULL(ЗаказТовары.Номенклатура.Родитель, ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)) КАК ГруппаНоменклатуры,
    СУММА(ЕСТЬNULL(ЗаказТовары.Сумма, 0)) КАК СуммаПродаж
ИЗ
    Справочник.Партнеры КАК Партнеры
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Н_СкладыКлиентов КАК СкладыКлиентов
        ПО Партнеры.Ссылка = СкладыКлиентов.Владелец
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК Заказ
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.Товары КАК ЗаказТовары
        ПО Заказ.Ссылка = ЗаказТовары.Ссылка
    ПО Партнеры.Ссылка = Заказ.Партнер
        И СкладыКлиентов.Ссылка = Заказ.СкладКлиента
ГДЕ
    (Заказ.Дата МЕЖДУ &НачДата И &КонДата ИЛИ Заказ.Ссылка ЕСТЬ NULL)
    И (Заказ.Организация = &Орг ИЛИ &Орг = ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка))

СГРУППИРОВАТЬ ПО
    Партнеры.Ссылка,
    СкладыКлиентов.Ссылка,
    ЗаказТовары.Номенклатура.Родитель

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

Настройка структуры отчета для вывода сумм

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

  1. Создайте новый вариант отчета и добавьте элемент Таблица.
  2. В Строки таблицы добавьте группировки: Клиент, СкладКлиента.
  3. В Колонки таблицы добавьте группировку: ГруппаНоменклатуры.
  4. Перейдите на вкладку Выбранные поля именно для всей ТАБЛИЦЫ (а не для отдельных группировок) и добавьте туда ресурс СуммаПродаж.

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

Как вывести всех клиентов, даже если продаж не было?

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

Рассмотрим вариант с ОБЪЕДИНИТЬ ВСЕ в одном наборе данных:


// 1. Получаем всех клиентов и склады
ВЫБРАТЬ
    Партнеры.Ссылка КАК Клиент,
    СкладыКлиентов.Ссылка КАК СкладКлиента,
    ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) КАК ГруппаНоменклатуры,
    0 КАК Сумма
ИЗ
    Справочник.Партнеры КАК Партнеры
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Н_СкладыКлиентов КАК СкладыКлиентов
    ПО Партнеры.Ссылка = СкладыКлиентов.Владелец

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

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

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

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

← На главную