Как запретить СКД фильтровать одну из таблиц в пакете запросов при совпадении имен полей

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

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

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

Выясним причину: как работает оптимизатор СКД

Разберем ситуацию изнутри. Когда в схеме компоновки данных включена опция «Автозаполнение», система берет на себя задачу анализа текста запроса. СКД «просматривает» все временные таблицы и итоговый запрос. Если она находит поле, которое пользователь выбрал в настройках отбора, она автоматически модифицирует текст SQL-запроса, добавляя условия фильтрации во все части пакета, где это поле фигурирует.

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

Решение №1: Отключение автозаполнения и ручная настройка полей

Самый надежный способ, который помог автору темы, — это отказ от автоматического управления полями. Проанализируем этот процесс по шагам:

  1. Откроем макет схемы компоновки данных и перейдем на вкладку «Наборы данных».
  2. Для конкретного набора данных (запроса) снимем флажок «Автозаполнение». Это действие говорит системе: «Я сам определю, какие поля доступны для выбора и куда именно накладывать условия».
  3. Перейдем в конструктор запроса. Теперь нам необходимо явно указать, какие поля будут использоваться в компоновке.
  4. На вкладке «Компоновка данных» в конструкторе запроса (не путать с основной вкладкой настроек СКД) мы должны вручную перетащить нужные поля в список доступных.
  5. Для того поля, которое «конфликтует» в разных таблицах, зададим разные псевдонимы в рамках компоновки. Например, для первой таблицы оставим имя Товар, а для второй — ТоварТекст.

Таким образом, когда пользователь наложит отбор на поле Товар, СКД применит его только к тем частям запроса, где явно указана связь с этим псевдонимом, и проигнорирует вторую таблицу.

Решение №2: Использование расширений языка запросов (фигурные скобки)

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

Расширение языка запросов СКД позволяет точечно управлять местами наложения отборов. Если мы хотим, чтобы условие накладывалось только в основном запросе, а временные таблицы оставались «нетронутыми», мы можем явно прописать секцию ГДЕ в расширении:


ВЫБРАТЬ
    ТЗ_Данные.Номенклатура КАК Номенклатура,
    ТЗ_Данные.Количество КАК Количество
ИЗ
    ВТ_ПервичныеДанные КАК ТЗ_Данные
{ГДЕ
    ТЗ_Данные.Номенклатура.* КАК Номенклатура}

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

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

Проанализируем ситуацию, когда мы не хотим менять основной текст запроса, но нам нужно разделить логику полей. В конструкторе запроса СКД есть специальная вкладка «Компоновка данных». Она содержит три подвкладки: «Поля», «Условия» и «Таблицы».

Рассмотрим, как использовать вкладку «Условия»:

  1. Найдем в списке таблиц ту временную таблицу, которую НЕ нужно фильтровать.
  2. Если в ней выбрано поле с «опасным» именем, мы можем просто не добавлять его на вкладку «Условия» для данной конкретной таблицы.
  3. Если же поле необходимо для отбора, но под другим именем, добавим его и укажем уникальный Псевдоним.

Это позволяет оставить визуально одинаковые имена в SQL-запросе (для удобства чтения или объединения), но сделать их абсолютно разными сущностями для генератора отчетов СКД.

Решение №4: Ограничение доступности полей

Посмотрим на проблему с точки зрения пользовательского интерфейса. В схеме компоновки на вкладке «Наборы данных» есть колонка с иконкой «перечеркнутой воронки» — «Ограничение отбора».

Если мы создали два поля (например, Дата из первой таблицы и ДатаСтрокой из второй), мы можем установить флажок ограничения отбора для поля ДатаСтрокой. В этом случае:

Технические нюансы работы с временными таблицами

Важно понимать, что СКД старается «пробросить» фильтры во временные таблицы как можно раньше. Это критически важно для производительности. Если в основной таблице 10 миллионов записей, а пользователь хочет отчет по одному контрагенту, СКД добавит ГДЕ Контрагент = &Параметр прямо в первый запрос, создающий временную таблицу.

Рассмотрим пример кода, где это может вызвать ошибку типов:


// ВТ_Данные1 - здесь Поле1 имеет тип СправочникСсылка.Организации
ВЫБРАТЬ Поле1, Сумма ИЗ Документ.Реализация КАК Реализация;

// ВТ_Данные2 - здесь Поле1 имеет тип Строка (например, ГУИД или код)
ВЫБРАТЬ Поле1, Комментарий ИЗ РегистрСведений.ДополнительныеСведения КАК Сведения;

Если СКД увидит в настройках отбор по Организации, она добавит условие во второй запрос: ГДЕ Сведения.Поле1 = &ПараметрОрганизация. Так как Поле1 во второй таблице — строка, СУБД вернет пустой результат. Чтобы этого избежать, используйте псевдонимы компоновки, как было описано выше. Для второй таблицы в конструкторе СКД (вкладка «Компоновка данных») укажите для Поле1 путь к данным: Поле1_Строка.

Подведем итоги

Проанализировав все способы, можно сделать вывод: наиболее «чистым» решением является явное управление полями компоновки. Не полагайтесь на «Автозаполнение», если ваш пакет запросов сложнее одного простого выбора из одной таблицы.

Основные рекомендации:

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

Соблюдение этих правил позволит вам создавать гибкие и производительные отчеты, избегая трудноуловимых ошибок с «исчезновением» данных из-за некорректной работы оптимизатора запросов.

← На главную