Почему в СКД не работает необязательное условие в фигурных скобках и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда условие, заключенное в фигурные скобки {ГДЕ ...}, попросту игнорируется системой. Особенно остро эта проблема проявляется при использовании временных таблиц. В результате отчет либо выводит лишние данные, либо работает крайне медленно, так как фильтрация не происходит на уровне запроса к базе данных.

В этой статье мы разберем, почему оптимизатор СКД может исключать ваши условия, и как правильно настроить схему компоновки, чтобы отборы работали корректно и эффективно.

Анализ причины: почему СКД «вырезает» условие

Система компоновки данных — это не просто механизм выполнения запросов, это интеллектуальный генератор. Перед исполнением СКД анализирует итоговые настройки отчета (выбранные поля, группировки, отборы) и модифицирует исходный текст запроса. Если поле, указанное в фигурных скобках внутри временной таблицы, не задействовано в финальной выборке или не определено в метаданных компоновки как доступное для отбора именно в этом узле, оптимизатор решит, что это условие избыточно, и удалит блок {ГДЕ ...} для упрощения запроса.

Рассмотрим типичный пример проблемного кода во временной таблице:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    СостоянияСотрудников.Сотрудник КАК Сотрудник,
    СостоянияСотрудников.Состояние КАК Состояние
ПОМЕСТИТЬ ВТСостояния
ИЗ
    РегистрСведений.СостоянияСотрудников КАК СостоянияСотрудников
ГДЕ
    СостоянияСотрудников.Период < &ОкончаниеПериода
{ГДЕ
    (СостоянияСотрудников.Сотрудник В (&Сотрудники)) КАК ОтборСотрудник}
;

В данном случае, если параметр &Сотрудники или псевдоним ОтборСотрудник не привязаны к конкретным полям компоновки, СКД проигнорирует этот фрагмент.

Решение 1: Настройка закладки «Компоновка данных» в конструкторе запроса

Самая распространенная ошибка — задание условия в тексте запроса без соответствующей настройки расширения языка запросов. Для того чтобы СКД «увидела» ваше необязательное условие, выполним следующие шаги:

  1. Откроем конструктор запроса в наборе данных СКД.
  2. Перейдем на закладку Компоновка данных.
  3. В подразделе Поля проверим, добавлено ли поле СостоянияСотрудников.Сотрудник. Важно, чтобы система понимала: это поле доступно для отбора именно внутри данной временной таблицы.
  4. В подразделе Условия на этой же закладке можно явно указать доступные условия. Если мы используем конструкцию {ГДЕ...} в тексте, она должна соответствовать доступным полям отбора в настройках компоновки.

Важный момент: Если вы используете псевдоним условия (например, КАК ОтборСотрудник), то в пользовательских настройках отбора на вкладке «Настройки» должен фигурировать именно этот элемент. Если пользователь не установил этот отбор, СКД закономерно исключит его из запроса.

Решение 2: Использование параметров вместо расширения ГДЕ

Если условие по списку сотрудников должно применяться всегда (или почти всегда) и вы заметили, что использование фигурных скобок приводит к получению всех записей из базы (что сильно замедляет отчет), стоит рассмотреть переход к обычным параметрам запроса.

Уберем фигурные скобки и сделаем параметр обязательным:


ИЗ
    РегистрСведений.СостоянияСотрудников КАК СостоянияСотрудников
ГДЕ
    СостоянияСотрудников.Период < &ОкончаниеПериода
    И СостоянияСотрудников.Сотрудник В (&Сотрудники)

В этом случае СКД гарантированно включит условие в запрос. Чтобы отчет не выдавал ошибку, когда список сотрудников пуст, в настройках параметра на закладке Параметры в СКД можно установить флаг Доступные значения или обрабатывать пустой список программно, передавая в него массив всех сотрудников (хотя это не всегда оптимально).

Решение 3: Проверка программной установки параметров

Если вы устанавливаете значения параметров программно через КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(), помните, что это влияет только на явные параметры (те, что с амперсандом &). Если же ваше условие в фигурных скобках завязано на Отбор, то и устанавливать его нужно через коллекцию КомпоновщикНастроек.Настройки.Отбор.Элементы.

Проанализируем ситуацию: если поле Сотрудник присутствует в итоговом запросе (выводится в отчет), СКД может автоматически наложить на него фильтр в самом конце, после выполнения всех временных таблиц. Но для производительности нам нужно, чтобы фильтр отработал «внутри» первой же выборки. Для этого:

Рекомендация по работе с регистрами сведений

При работе с такими данными, как состояния сотрудников, зачастую эффективнее использовать виртуальные таблицы, например, СрезПоследних. У виртуальных таблиц есть штатные параметры (Период, Условие), которые СКД обрабатывает очень эффективно. Если ваша задача позволяет получить данные через СрезПоследних, это будет более «кошерным» и быстрым решением, чем фильтрация физической таблицы в ГДЕ.

Разберем пример обращения к виртуальной таблице с параметрами компоновки:


ВЫБРАТЬ
    Срез.Сотрудник,
    Срез.Состояние
ИЗ
    РегистрСведений.СостоянияСотрудников.СрезПоследних(&Период, {Сотрудник.*}) КАК Срез

Здесь конструкция {Сотрудник.*} позволяет СКД автоматически подставлять любые отборы по сотруднику и его реквизитам непосредственно в параметры виртуальной таблицы, что обеспечивает максимальную производительность.

Итоги

Для исправления работы необязательного условия выполним проверку по списку:

  1. Убедимся, что поле отбора активно в настройках пользователя (вкладка «Отбор»).
  2. Проверим наличие поля в секции Поля на закладке Компоновка данных в конструкторе запроса.
  3. Посмотрим итоговый запрос через Консоль СКД (это лучший способ увидеть, как платформа изменила ваш текст).
  4. Если скорость работы критична, откажемся от фигурных скобок во временных таблицах в пользу обязательных параметров или механизмов виртуальных таблиц.
← На главную