Почему запрос 1С с условием В ИЕРАРХИИ возвращает данные при незаполненном параметре?

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

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

Анализ исходного запроса

Проанализируем структуру запроса, который вызвал вопросы. В нем используется вложенная выборка из виртуальной таблицы оборотов регистра накопления Продажи. Внутри вложенного запроса применяется конструкция ВЫБОР, которая проверяет вхождение номенклатуры в иерархию параметра &ГотоваяЕда.


ВЫБРАТЬ
    ВложенныйЗапрос.Магазин КАК Магазин,
    СУММА(ВложенныйЗапрос.ГотоваяЕда) КАК ГотоваяЕда
ИЗ
    (ВЫБРАТЬ
        ПродажиОбороты.Магазин КАК Магазин,
        ВЫБОР
            КОГДА ПродажиОбороты.Номенклатура В ИЕРАРХИИ (&ГотоваяЕда)
                ТОГДА ПродажиОбороты.СтоимостьОборот
            ИНАЧЕ 0
        КОНЕЦ КАК ГотоваяЕда
    ИЗ
        РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Период, ) КАК ПродажиОбороты) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Магазин
ИТОГИ
    СУММА(ГотоваяЕда)
ПО
    ОБЩИЕ

На первый взгляд кажется, что если параметр &ГотоваяЕда не заполнен, то условие В ИЕРАРХИИ всегда должно возвращать Ложь, а колонка «ГотоваяЕда» должна заполниться нулями. Однако на практике пользователь видит данные. Выясним почему.

Причина №1: Пустая ссылка в параметре

Когда мы работаем в консоли запросов и не заполняем параметр ссылочного типа (например, СправочникСсылка.Номенклатура), платформа часто подставляет туда так называемую Пустую ссылку. В языке 1С пустая ссылка — это не NULL и не отсутствие значения, это конкретный объект с пустым уникальным идентификатором (UUID из нулей).

Рассмотрим, как оператор В ИЕРАРХИИ обрабатывает пустую ссылку. Если справочник иерархический (как «Номенклатура»), то условие Номенклатура В ИЕРАРХИИ (&ПустаяСсылка) может интерпретироваться СУБД как поиск элементов, у которых поле Родитель также является пустой ссылкой. Это характерно для элементов «верхнего уровня» (корневых папок и товаров), у которых нет вышестоящего родителя. Таким образом, в выборку попадают все товары, не включенные ни в одну группу, что и создает иллюзию «игнорирования» фильтра.

Причина №2: Логика конструкции ВЫБОР и группировки

Важно обратить внимание на то, где именно стоит условие. Оно находится внутри ВЫБОР, а не в секции ГДЕ. Это означает следующее:

  1. Запрос в любом случае прочитает все записи из виртуальной таблицы Продажи.Обороты за указанный период по всем магазинам.
  2. Для каждой строки будет вычислено значение: если номенклатура подошла под условие — берется СтоимостьОборот, если нет — 0.
  3. В основном запросе происходит группировка по магазинам.

Если в параметре &ГотоваяЕда передано значение, которое система смогла сопоставить (например, пустая ссылка, под которую попали корневые товары), суммы по этим товарам будут выведены. Если же условие действительно не сработало ни для одной строки, запрос все равно вернет список всех магазинов, но с нулевыми суммами в колонке ГотоваяЕда. Из-за наличия итогов (ИТОГИ ПО ОБЩИЕ) в консоли может отображаться общая строка, что также может запутать пользователя.

Разберем правильный подход к фильтрации

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

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

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

Перепишем запрос правильно:


ВЫБРАТЬ
    ПродажиОбороты.Магазин КАК Магазин,
    СУММА(ПродажиОбороты.СтоимостьОборот) КАК ГотоваяЕда
ИЗ
    РегистрНакопления.Продажи.Обороты(
        &НачалоПериода, 
        &КонецПериода, 
        , 
        Номенклатура В ИЕРАРХИИ (&ГотоваяЕда)
    ) КАК ПродажиОбороты
СГРУППИРОВАТЬ ПО
    ПродажиОбороты.Магазин
ИТОГИ
    СУММА(ГотоваяЕда)
ПО
    ОБЩИЕ

В данном варианте, если в &ГотоваяЕда будет передана пустая ссылка, виртуальная таблица сразу отсечет все лишнее (или выберет корень, в зависимости от настроек платформы), но сам запрос станет значительно быстрее.

Поведение в СКД (Система компоновки данных)

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

Проверка и отладка

Чтобы окончательно выяснить причину появления данных в вашем конкретном случае, проанализируем ситуацию по шагам:

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

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

Таким образом, мы выяснили, что «магия» появления данных при пустом параметре кроется либо в специфике обработки пустых ссылок в иерархических структурах, либо в особенностях работы конструкций ВЫБОР и механизмов СКД. Понимание этих основ позволяет писать надежные и предсказуемые отчеты в 1С.

← На главную