При разработке отчетов в системе компоновки данных (СКД) часто возникает задача вывести в один отчет данные из двух табличных частей одного документа. Если эти табличные части никак не связаны между собой прямыми ссылками, а объединены только реквизитами шапки (например, ссылкой на документ или подразделением), при неправильной настройке запроса или структуры компоновки происходит декартово перемножение строк. В результате данные задваиваются, а общие итоги рассчитываются некорректно.
Рассмотрим причину возникновения этой проблемы и разберем по шагам несколько рабочих способов ее решения.
Когда мы соединяем в одном запросе через ЛЕВОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ две табличные части документа по ссылке, платформа 1С на каждую строку из первой табличной части подтягивает все строки из второй. Если в первой таблице 3 строки, а во второй 4, результат запроса вернет 12 строк. Это и есть декартово произведение записей.
Даже если использовать объединение ОБЪЕДИНИТЬ ВСЕ, без правильного разделения полей ресурсов и настройки структуры отчета стандартные агрегатные функции СКД могут ошибочно подтягивать значение из соседней таблицы или некорректно суммировать NULL-значения.
Проанализируем первый подход. В одном наборе данных-запросе выбираются записи первой табличной части, а затем через оператор ОБЪЕДИНИТЬ ВСЕ — записи второй табличной части. При этом для уникальных колонок первой таблицы во второй части выборки подставляются NULL, и наоборот.
Рассмотрим пример текста запроса для документа с двумя табличными частями преподавателей и старших преподавателей:
ВЫБРАТЬ
МотивацияПреподавателейПреподаватели.Сотрудник КАК Преподаватель,
МотивацияПреподавателейПреподаватели.Ссылка.Подразделение КАК Подразделение,
МотивацияПреподавателейПреподаватели.СреднийБалл КАК СреднийБаллПреподаватель,
МотивацияПреподавателейПреподаватели.ОценкаПоБонусу КАК ОценкаПоБонусу,
МотивацияПреподавателейПреподаватели.Начислено КАК НачисленоПреподаватель,
МотивацияПреподавателейПреподаватели.СуммаБонусВопрос КАК СуммаБонусВопросПреподаватель,
МотивацияПреподавателейПреподаватели.СуммаБонусов КАК СуммаБонусовПреподаватель,
NULL КАК ПроцентПоложительныхРезультатов,
NULL КАК НачисленоСтаршийПреподаватель,
NULL КАК СтаршийПреподаватель,
NULL КАК СуммаБонусВопросСтаршийПреподаватель,
NULL КАК СуммаБонусовСтаршийПреподаватель
ИЗ
Документ.МотивацияПреподавателей.Преподаватели КАК МотивацияПреподавателейПреподаватели
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
NULL,
МотивацияПреподавателейСтаршиеПреподаватели.Ссылка.Подразделение,
NULL,
NULL,
NULL,
NULL,
NULL,
МотивацияПреподавателейСтаршиеПреподаватели.ПроцентПоложительныхРезультатов,
МотивацияПреподавателейСтаршиеПреподаватели.Начислено,
МотивацияПреподавателейСтаршиеПреподаватели.Сотрудник,
МотивацияПреподавателейСтаршиеПреподаватели.СуммаБонусВопрос,
МотивацияПреподавателейСтаршиеПреподаватели.СуммаБонусов
ИЗ
Документ.МотивацияПреподавателей.СтаршиеПреподаватели КАК МотивацияПреподавателейСтаршиеПреподаватели
Чтобы правильно вывести такие данные на макет и посчитать итоги, выполним следующие шаги:
СуммаБонусовПреподаватель, а по второй — СуммаБонусовСтаршийПреподаватель.Подразделение). Внутрь нее добавим две параллельные группировки (на одном уровне под группировкой подразделения): первая для вывода полей первой табличной части, вторая — для полей второй табличной части.Альтернативный и более прозрачный подход заключается в разделении запросов по разным наборам данных:
НаборДанных2 с НаборДанных1 по полю Ссылка, а также НаборДанных3 с НаборДанных1 по полю Ссылка.При такой схеме СКД выводит подчиненные таблицы независимо друг от друга в рамках родительской группировки документа или подразделения.
Еще один способ — создание на вкладке «Наборы данных» элемента типа «Набор данных — Объединение». Внутрь этого объединения помещаются два отдельных набора данных-запроса (каждый для своей табличной части). В этом случае не нужно настраивать связи наборов по левому соединению, а платформа автоматически суммирует ресурсы по совпадающим полям на всех уровнях группировки.
Разберем ситуации, когда требуется получить общие итоги по подразделению или документу, складывая показатели из двух табличных частей.
Если ресурсы первой и второй табличной части называются по-разному (например, СуммаБонусовПреподаватель и СуммаБонусовСтаршийПреподаватель), в настройках на вкладке «Ресурсы» мы можем добавить вычисляемый ресурс или задать произвольное выражение расчета итогов:
В колонке «Выражение» для общего итогового поля пишем:
Сумма(СуммаБонусовПреподаватель) + Сумма(СуммаБонусовСтаршийПреподаватель)
Таким образом, итог по подразделению будет корректно рассчитываться независимо от того, есть ли данные в первой, во второй или в обеих табличных частях одновременно.