При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда условие, заключенное в фигурные скобки {ГДЕ ...}, попросту игнорируется системой. Особенно остро эта проблема проявляется при использовании временных таблиц. В результате отчет либо выводит лишние данные, либо работает крайне медленно, так как фильтрация не происходит на уровне запроса к базе данных.
В этой статье мы разберем, почему оптимизатор СКД может исключать ваши условия, и как правильно настроить схему компоновки, чтобы отборы работали корректно и эффективно.
Система компоновки данных — это не просто механизм выполнения запросов, это интеллектуальный генератор. Перед исполнением СКД анализирует итоговые настройки отчета (выбранные поля, группировки, отборы) и модифицирует исходный текст запроса. Если поле, указанное в фигурных скобках внутри временной таблицы, не задействовано в финальной выборке или не определено в метаданных компоновки как доступное для отбора именно в этом узле, оптимизатор решит, что это условие избыточно, и удалит блок {ГДЕ ...} для упрощения запроса.
Рассмотрим типичный пример проблемного кода во временной таблице:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
СостоянияСотрудников.Сотрудник КАК Сотрудник,
СостоянияСотрудников.Состояние КАК Состояние
ПОМЕСТИТЬ ВТСостояния
ИЗ
РегистрСведений.СостоянияСотрудников КАК СостоянияСотрудников
ГДЕ
СостоянияСотрудников.Период < &ОкончаниеПериода
{ГДЕ
(СостоянияСотрудников.Сотрудник В (&Сотрудники)) КАК ОтборСотрудник}
;
В данном случае, если параметр &Сотрудники или псевдоним ОтборСотрудник не привязаны к конкретным полям компоновки, СКД проигнорирует этот фрагмент.
Самая распространенная ошибка — задание условия в тексте запроса без соответствующей настройки расширения языка запросов. Для того чтобы СКД «увидела» ваше необязательное условие, выполним следующие шаги:
СостоянияСотрудников.Сотрудник. Важно, чтобы система понимала: это поле доступно для отбора именно внутри данной временной таблицы.{ГДЕ...} в тексте, она должна соответствовать доступным полям отбора в настройках компоновки.Важный момент: Если вы используете псевдоним условия (например, КАК ОтборСотрудник), то в пользовательских настройках отбора на вкладке «Настройки» должен фигурировать именно этот элемент. Если пользователь не установил этот отбор, СКД закономерно исключит его из запроса.
Если условие по списку сотрудников должно применяться всегда (или почти всегда) и вы заметили, что использование фигурных скобок приводит к получению всех записей из базы (что сильно замедляет отчет), стоит рассмотреть переход к обычным параметрам запроса.
Уберем фигурные скобки и сделаем параметр обязательным:
ИЗ
РегистрСведений.СостоянияСотрудников КАК СостоянияСотрудников
ГДЕ
СостоянияСотрудников.Период < &ОкончаниеПериода
И СостоянияСотрудников.Сотрудник В (&Сотрудники)
В этом случае СКД гарантированно включит условие в запрос. Чтобы отчет не выдавал ошибку, когда список сотрудников пуст, в настройках параметра на закладке Параметры в СКД можно установить флаг Доступные значения или обрабатывать пустой список программно, передавая в него массив всех сотрудников (хотя это не всегда оптимально).
Если вы устанавливаете значения параметров программно через КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(), помните, что это влияет только на явные параметры (те, что с амперсандом &). Если же ваше условие в фигурных скобках завязано на Отбор, то и устанавливать его нужно через коллекцию КомпоновщикНастроек.Настройки.Отбор.Элементы.
Проанализируем ситуацию: если поле Сотрудник присутствует в итоговом запросе (выводится в отчет), СКД может автоматически наложить на него фильтр в самом конце, после выполнения всех временных таблиц. Но для производительности нам нужно, чтобы фильтр отработал «внутри» первой же выборки. Для этого:
Автозаполнение выключено, вам придется вручную прописать каждое поле на закладке Компоновка данных для каждой временной таблицы, где это поле используется.При работе с такими данными, как состояния сотрудников, зачастую эффективнее использовать виртуальные таблицы, например, СрезПоследних. У виртуальных таблиц есть штатные параметры (Период, Условие), которые СКД обрабатывает очень эффективно. Если ваша задача позволяет получить данные через СрезПоследних, это будет более «кошерным» и быстрым решением, чем фильтрация физической таблицы в ГДЕ.
Разберем пример обращения к виртуальной таблице с параметрами компоновки:
ВЫБРАТЬ
Срез.Сотрудник,
Срез.Состояние
ИЗ
РегистрСведений.СостоянияСотрудников.СрезПоследних(&Период, {Сотрудник.*}) КАК Срез
Здесь конструкция {Сотрудник.*} позволяет СКД автоматически подставлять любые отборы по сотруднику и его реквизитам непосредственно в параметры виртуальной таблицы, что обеспечивает максимальную производительность.
Для исправления работы необязательного условия выполним проверку по списку: