Как наложить необязательное условие в секции ИМЕЮЩИЕ в 1С:СКД

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

При разработке сложных отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью наложить условие на агрегатные функции (суммы, количества), но сделать это условие зависимым от выбора пользователя. Стандартный механизм расширения языка запросов 1С, использующий фигурные скобки {}, отлично работает в секциях ГДЕ или ВЫБРАТЬ, но при попытке использовать его в секции ИМЕЮЩИЕ (HAVING) система выдает синтаксическую ошибку. Давайте подробно разберем, почему так происходит и какими способами можно реализовать данную задачу.

Проблема использования фигурных скобок в ИМЕЮЩИЕ

Проанализируем стандартное поведение платформы. Конструкция {ИМЕЮЩИЕ...} не поддерживается синтаксисом расширения СКД. Это ограничение часто сбивает с толку, так как логика подсказывает, что если мы можем сделать необязательным фильтр по полю в ГДЕ, то должны иметь возможность сделать то же самое и для итогов. Однако на практике попытка написать такой запрос приведет к ошибке исполнения.

Рассмотрим ситуацию: нам нужно выводить строки только с положительным планом, если установлен флаг &ТолькоПлан. Если флаг снят, отчет должен выводить все данные, включая те, где план равен нулю или отсутствует. Выясним, как это реализовать без дублирования запросов.

Способ 1. Использование булевой логики в условии запроса

Самый простой способ, который не требует переработки структуры запроса, заключается в использовании логического оператора ИЛИ. Мы можем прописать условие таким образом, чтобы оно либо проверяло сумму, либо игнорировалось, если параметр не заполнен или равен Ложь.

Посмотрим на пример реализации в тексте запроса:


ВЫБРАТЬ
    ВТ_Объединенная.СтатьяФинансирования КАК СтатьяФинансирования,
    СУММА(ВТ_Объединенная.СуммаПлан) КАК СуммаПлан
ИЗ
    ВТ_Объединенная КАК ВТ_Объединенная
СГРУППИРОВАТЬ ПО
    ВТ_Объединенная.СтатьяФинансирования
ИМЕЮЩИЕ
    (СУММА(ВТ_Объединенная.СуммаПлан) > 0 ИЛИ НЕ &ТолькоПлан)

Проанализируем, как работает это условие:

  1. Если параметр &ТолькоПлан установлен в значение Истина, то вторая часть условия (НЕ &ТолькоПлан) превращается в Ложь. В итоге результат зависит только от первой части: СУММА(...) > 0.
  2. Если параметр &ТолькоПлан установлен в Ложь, то выражение НЕ &ТолькоПлан всегда дает Истина. Согласно правилам логики, если одна часть условия в операторе ИЛИ истинна, то и всё выражение истинно. Условие ИМЕЮЩИЕ перестает что-либо фильтровать.

Важный нюанс: при таком подходе параметр &ТолькоПлан должен быть обязательным и всегда иметь булево значение (Истина/Ложь), иначе вы можете столкнуться с ошибкой "Несоответствие типов" или некорректной работой при значении NULL.

Способ 2. Использование вложенного запроса (Обертка)

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

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

Разберем этот метод по шагам:


ВЫБРАТЬ
    ИтоговыеДанные.СтатьяФинансирования,
    ИтоговыеДанные.СуммаПлан
ИЗ
    (ВЫБРАТЬ
        ВТ_Объединенная.СтатьяФинансирования КАК СтатьяФинансирования,
        СУММА(ВТ_Объединенная.СуммаПлан) КАК СуммаПлан
    ИЗ
        ВТ_Объединенная КАК ВТ_Объединенная
    СГРУППИРОВАТЬ ПО
        ВТ_Объединенная.СтатьяФинансирования) КАК ИтоговыеДанные
ГДЕ
    {&ИтоговыеДанные.СуммаПлан > 0}

В данном примере мы видим, что поле СуммаПлан во внешнем запросе уже не требует функции СУММА(), так как она была вычислена внутри. Теперь мы можем спокойно использовать фигурные скобки {}. Если пользователь не заполнит параметр или не включит соответствующий отбор, СКД просто проигнорирует секцию ГДЕ, и мы получим все записи.

Способ 3. Перенос фильтрации в настройки СКД

Рассмотрим еще один профессиональный подход: вообще отказаться от ручного написания ИМЕЮЩИЕ в тексте запроса. СКД — это мощный конструктор, который умеет генерировать секцию ИМЕЮЩИЕ автоматически.

Для этого выполним следующие действия:

  1. В схеме компоновки данных на вкладке "Наборы данных" убедимся, что числовое поле (например, СуммаПлан) добавлено в список доступных полей.
  2. На вкладке "Ресурсы" добавим это поле как ресурс (обычно СУММА(СуммаПлан)).
  3. Перейдем на вкладку "Настройки", выберем нужную группировку или весь отчет и откроем вкладку "Отбор".
  4. Добавим новый элемент отбора: Левое значение — СуммаПлан, Вид сравнения — Больше, Правое значение — 0.

Когда вы накладываете отбор на поле, которое является ресурсом, СКД сама понимает, что это условие должно попасть в секцию ИМЕЮЩИЕ итогового запроса к базе данных. Чтобы сделать этот отбор "необязательным", достаточно просто предоставить пользователю возможность включать или выключать его в настройках отчета (вывести в быстрые настройки).

Сравнение методов и рекомендации

Проанализируем ситуацию и выберем оптимальный путь:

Таким образом, хотя прямое наложение фигурных скобок на ИМЕЮЩИЕ невозможно, использование вложенных запросов или грамотная настройка ресурсов в СКД полностью решают задачу динамической фильтрации итогов.

← На главную