Как в запросе 1С проверить, является ли переданный параметр группой или элементом?

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

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

Способ 1. Использование оператора ВЫРАЗИТЬ в блоке ВЫБРАТЬ

Самый распространенный и технически верный способ обратиться к реквизитам ссылки, переданной через параметр, — это явное приведение типа. Платформа должна «понимать», к таблице какого именно справочника вы обращаетесь, чтобы извлечь поле ЭтоГруппа. Рассмотрим пример кода, который можно использовать в консоли запросов или программно:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    ВЫБОР
        КОГДА ВЫРАЗИТЬ(&ПарамНоменклатура КАК Справочник.Номенклатура).ЭтоГруппа
            ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ЭтоГруппаПараметра
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка = &ПарамНоменклатура

Разберем, почему это работает. Оператор ВЫРАЗИТЬ указывает системе, что параметр &ПарамНоменклатура имеет тип Справочник.Номенклатура. Это позволяет разыменовать параметр и обратиться к его внутренним полям. Однако важно помнить, что такая конструкция работает в блоке ВЫБРАТЬ, но может вызвать ошибки или работать нестабильно в блоке ГДЕ в некоторых версиях платформы или специфических СУБД.

Способ 2. Передача признака группы отдельным параметром

Проанализируем ситуацию с точки зрения производительности. Когда мы используем ВЫРАЗИТЬ(...).ЭтоГруппа, СУБД вынуждена выполнять неявное левое соединение с таблицей справочника, чтобы получить значение этого поля. Если запрос выполняется в цикле (хотя этого следует избегать) или обрабатывает огромные массивы данных, это может замедлить работу.

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


// Предположим, ОбъектСсылка — это наша ссылка на номенклатуру
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |   Номенклатура.Ссылка = &Параметр
    |   И &ЭтоГруппа = ИСТИНА";

Запрос.УстановитьПараметр("Параметр", ОбъектСсылка);
Запрос.УстановитьПараметр("ЭтоГруппа", ОбъектСсылка.ЭтоГруппа);

Этот метод исключает лишние соединения внутри SQL-запроса, так как логика проверки выносится на уровень сервера приложений 1С.

Способ 3. Проверка через подзапрос в условии ГДЕ

Если вам необходимо выполнить фильтрацию в зависимости от типа ссылки (группа/элемент) непосредственно в блоке ГДЕ, и вы не хотите передавать дополнительный параметр, можно использовать вложенный запрос. Этот метод более стабилен, чем попытки использовать ВЫРАЗИТЬ в условиях.

Выясним, как это выглядит на практике:


ВЫБРАТЬ
    Номенклатура.Ссылка
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В (
        ВЫБРАТЬ
            Т.Ссылка
        ИЗ
            Справочник.Номенклатура КАК Т
        ГДЕ
            Т.Ссылка = &ПарамНоменклатура
            И Т.ЭтоГруппа = ИСТИНА
    )

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

Важные технические нюансы

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

  1. Тип иерархии: Поле ЭтоГруппа существует только в справочниках с типом «Иерархия групп и элементов». Если в настройках метаданных установлена «Иерархия элементов», то этого поля в таблице просто не будет. В такой иерархии любой элемент может быть родителем, и проверка на «группу» теряет технический смысл.
  2. Составные типы данных: Если параметр имеет составной тип (например, ЛюбаяСсылка), использование ВЫРАЗИТЬ становится обязательным. Без этого система не сможет определить, из какой физической таблицы базы данных нужно извлекать реквизит ЭтоГруппа.
  3. Пустые ссылки: Если в параметр передана пустая ссылка справочника, конструкция ВЫРАЗИТЬ(...).ЭтоГруппа вернет ЛОЖЬ. Программисту важно учитывать это в логике программы, чтобы пустая ссылка случайно не была обработана как обычный элемент.
  4. Производительность (Разыменование): Обращение через точку от параметра (разыменование) всегда ведет к созданию LEFT JOIN в SQL-запросе. Если вам нужно просто проверить условие В ИЕРАРХИИ, лучше использовать стандартный оператор, который оптимизирован платформой для работы как с группами, так и с элементами:

ГДЕ
    Номенклатура.Ссылка В ИЕРАРХИИ (&ПарамНоменклатура)

Данная конструкция автоматически обработает ситуацию: если в параметре группа — будут выбраны все вложенные элементы, если элемент — только он сам.

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

Мы проанализировали три основных способа проверки типа объекта в запросе. Для простых отчетов в консоли идеально подходит Способ 1 с использованием ВЫРАЗИТЬ. Для высоконагруженных систем и сложных алгоритмов лучше всего использовать Способ 2, передавая признак ЭтоГруппа как отдельный параметр типа Булево. Если же требуется сложная фильтрация внутри самого запроса без изменения программного кода вызова, оптимальным решением станет Способ 3 с подзапросом.

← На главную