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