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

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

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

Анализ проблемы: почему условие с параметром может не работать

Разберем ситуацию, когда в запросе используется конструкция вида ГДЕ БюджетОбороты.ГруппаРасходов.Наименование <> &Товар. На первый взгляд, логика верна, однако система может не отсеивать записи. Проанализируем основные причины этого поведения:

  1. Несоответствие типов данных: Если в параметре &Товар на вкладке "Параметры" СКД указан тип СправочникСсылка, а вы сравниваете его с полем Наименование (которое является строкой), условие никогда не будет истинным.
  2. Особенности работы СКД: Система компоновки данных — это не просто средство выполнения SQL-запросов, а мощный генератор. Если поле, по которому идет отбор, также вынесено в пользовательские настройки отбора, настройки пользователя могут перекрывать или конфликтовать с жестким условием в коде.
  3. Неявные соединения: Обращение через точку (ГруппаРасходов.Наименование) заставляет платформу создавать временную таблицу и выполнять соединение (JOIN). Если в основной таблице поле ГруппаРасходов не заполнено (имеет значение NULL), такое сравнение может привести к непредсказуемым результатам в итоговой выборке.

Решение 1: Прямое сравнение со строкой (быстрый, но небезопасный метод)

Как показала практика обсуждения на форуме, простейшим решением является использование строкового литерала прямо в тексте запроса. Посмотрим на пример:


ВЫБРАТЬ
    БюджетОбороты.ГруппаРасходов,
    БюджетОбороты.СуммаОборот
ИЗ
    РегистрНакопления.Бюджет.Обороты КАК БюджетОбороты
ГДЕ
    БюджетОбороты.ГруппаРасходов.Наименование <> "Товар"

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

Решение 2: Использование конструкции ЗНАЧЕНИЕ

Если элемент "Товар" является ключевым для логики отчета и создан в конфигураторе как предопределенный, наиболее правильным и быстрым способом будет использование оператора ЗНАЧЕНИЕ. Выясним преимущества этого подхода: сравнение идет по уникальному идентификатору (ссылке), что гораздо производительнее сравнения строк.

Рассмотрим пример кода:


ГДЕ
    БюджетОбороты.ГруппаРасходов <> ЗНАЧЕНИЕ(Справочник.ГруппыРасходов.Товар)

В этом случае системе не нужно обращаться к полю Наименование, что исключает лишние соединения таблиц и ускоряет выполнение запроса.

Решение 3: Правильная настройка параметров в СКД

Если нам нужно, чтобы значение "Товар" передавалось через параметр, важно убедиться в корректности настроек на вкладке "Параметры" в конструкторе схемы компоновки данных. Проанализируем шаги настройки:

  1. Убедимся, что для параметра &Товар выбран правильный тип данных: СправочникСсылка.ГруппыРасходов.
  2. Проверим, не стоит ли галочка "Ограничение доступности", если мы хотим, чтобы пользователь сам мог выбрать значение.
  3. В тексте запроса используем сравнение ссылок, а не наименований:

ГДЕ
    БюджетОбороты.ГруппаРасходов <> &Товар

Если мы хотим сравнить именно по строке, то тип параметра должен быть Строка, а в значении должно быть вписано точное наименование без лишних кавычек.

Решение 4: Оптимизация через параметры виртуальной таблицы

Для повышения производительности отчета, особенно если регистр содержит сотни тысяч записей, условия следует выносить из секции ГДЕ в параметры виртуальной таблицы. Рассмотрим подробнее, как это изменить в запросе:

Плохо (фильтрация после получения всех данных):


ИЗ
    РегистрНакопления.Бюджет.Обороты() КАК БюджетОбороты
ГДЕ
    БюджетОбороты.ГруппаРасходов <> &Товар

Хорошо (отсечение данных на этапе сборки итогов):


ИЗ
    РегистрНакопления.Бюджет.Обороты(, , , ГруппаРасходов <> &Товар) КАК БюджетОбороты

Такой подход позволяет СУБД работать эффективнее, так как объем передаваемых данных в основную выборку сокращается еще на стороне сервера базы данных.

Решение 5: Гибкие фильтры с использованием фигурных скобок

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


ВЫБРАТЬ
    БюджетОбороты.ГруппаРасходов,
    БюджетОбороты.СуммаОборот
ИЗ
    РегистрНакопления.Бюджет.Обороты КАК БюджетОбороты
ГДЕ
    {БюджетОбороты.ГруппаРасходов.* КАК ГруппаРасходов}

При такой записи СКД сама подставит нужные условия в итоговый SQL-запрос на основании того, что выбрал пользователь в настройках отбора на форме отчета.

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

Для того чтобы условия в СКД работали стабильно, придерживайтесь следующих правил:

Применяя эти методы, мы обеспечим надежную работу отчетов и корректную фильтрацию данных в любых условиях эксплуатации системы.

← На главную