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