В процессе разработки на платформе 1С:Предприятие 8 часто возникает необходимость логически разделить обработку данных в зависимости от того, что именно пользователь передал в качестве параметра запроса: конкретный элемент справочника или целую группу. Несмотря на кажущуюся простоту, прямое обращение к свойству ЭтоГруппа через точку от параметра (например, &Параметр.ЭтоГруппа) в языке запросов не допускается. В этой статье мы подробно разберем, как обойти это ограничение, проанализируем различные подходы и выясним, какой из них является наиболее оптимальным с точки зрения производительности.
Самый распространенный и технически верный способ обратиться к реквизитам ссылки, переданной через параметр, — это явное приведение типа. Платформа должна «понимать», к таблице какого именно справочника вы обращаетесь, чтобы извлечь поле ЭтоГруппа. Рассмотрим пример кода, который можно использовать в консоли запросов или программно:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
ВЫБОР
КОГДА ВЫРАЗИТЬ(&ПарамНоменклатура КАК Справочник.Номенклатура).ЭтоГруппа
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК ЭтоГруппаПараметра
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка = &ПарамНоменклатура
Разберем, почему это работает. Оператор ВЫРАЗИТЬ указывает системе, что параметр &ПарамНоменклатура имеет тип Справочник.Номенклатура. Это позволяет разыменовать параметр и обратиться к его внутренним полям. Однако важно помнить, что такая конструкция работает в блоке ВЫБРАТЬ, но может вызвать ошибки или работать нестабильно в блоке ГДЕ в некоторых версиях платформы или специфических СУБД.
Проанализируем ситуацию с точки зрения производительности. Когда мы используем ВЫРАЗИТЬ(...).ЭтоГруппа, СУБД вынуждена выполнять неявное левое соединение с таблицей справочника, чтобы получить значение этого поля. Если запрос выполняется в цикле (хотя этого следует избегать) или обрабатывает огромные массивы данных, это может замедлить работу.
Самый быстрый и «чистый» способ — определить, является ли объект группой, еще на стороне встроенного языка 1С и передать готовый результат в запрос. Посмотрим на программную реализацию:
// Предположим, ОбъектСсылка — это наша ссылка на номенклатуру
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Параметр
| И &ЭтоГруппа = ИСТИНА";
Запрос.УстановитьПараметр("Параметр", ОбъектСсылка);
Запрос.УстановитьПараметр("ЭтоГруппа", ОбъектСсылка.ЭтоГруппа);
Этот метод исключает лишние соединения внутри SQL-запроса, так как логика проверки выносится на уровень сервера приложений 1С.
Если вам необходимо выполнить фильтрацию в зависимости от типа ссылки (группа/элемент) непосредственно в блоке ГДЕ, и вы не хотите передавать дополнительный параметр, можно использовать вложенный запрос. Этот метод более стабилен, чем попытки использовать ВЫРАЗИТЬ в условиях.
Выясним, как это выглядит на практике:
ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка В (
ВЫБРАТЬ
Т.Ссылка
ИЗ
Справочник.Номенклатура КАК Т
ГДЕ
Т.Ссылка = &ПарамНоменклатура
И Т.ЭтоГруппа = ИСТИНА
)
Такой подход позволяет СУБД более эффективно построить план запроса, используя индексы по полю Ссылка.
Рассмотрим несколько критических моментов, которые часто упускают разработчики при проверке групп в запросах:
ЭтоГруппа существует только в справочниках с типом «Иерархия групп и элементов». Если в настройках метаданных установлена «Иерархия элементов», то этого поля в таблице просто не будет. В такой иерархии любой элемент может быть родителем, и проверка на «группу» теряет технический смысл.ЛюбаяСсылка), использование ВЫРАЗИТЬ становится обязательным. Без этого система не сможет определить, из какой физической таблицы базы данных нужно извлекать реквизит ЭтоГруппа.ВЫРАЗИТЬ(...).ЭтоГруппа вернет ЛОЖЬ. Программисту важно учитывать это в логике программы, чтобы пустая ссылка случайно не была обработана как обычный элемент.LEFT JOIN в SQL-запросе. Если вам нужно просто проверить условие В ИЕРАРХИИ, лучше использовать стандартный оператор, который оптимизирован платформой для работы как с группами, так и с элементами:
ГДЕ
Номенклатура.Ссылка В ИЕРАРХИИ (&ПарамНоменклатура)
Данная конструкция автоматически обработает ситуацию: если в параметре группа — будут выбраны все вложенные элементы, если элемент — только он сам.
Мы проанализировали три основных способа проверки типа объекта в запросе. Для простых отчетов в консоли идеально подходит Способ 1 с использованием ВЫРАЗИТЬ. Для высоконагруженных систем и сложных алгоритмов лучше всего использовать Способ 2, передавая признак ЭтоГруппа как отдельный параметр типа Булево. Если же требуется сложная фильтрация внутри самого запроса без изменения программного кода вызова, оптимальным решением станет Способ 3 с подзапросом.