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