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

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

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

В этой статье мы подробно разберем, почему стандартные подходы через точку не работают, и как правильно реализовать получение родителя предопределенного элемента внутри параметров виртуальной таблицы.

Анализ ограничений функции ЗНАЧЕНИЕ()

Многие начинающие разработчики пытаются использовать конструкцию вида ЗНАЧЕНИЕ(Справочник.ТипыДокументов.Диплом).Родитель. Разберем, почему это приводит к ошибке. Функция ЗНАЧЕНИЕ() в языке запросов 1С является литералом. Это означает, что она вычисляется еще на этапе подготовки (парсинга) запроса платформой, а не в момент его выполнения на сервере СУБД.

Ключевые особенности функции:

Следовательно, любая попытка извлечь родителя напрямую от литерала ЗНАЧЕНИЕ() будет пресечена синтаксическим контролем.

Решение 1: Использование вложенного запроса в параметрах виртуальной таблицы

Если нам принципиально не хочется передавать родителя как внешний параметр, мы можем воспользоваться механизмом подзапросов. Язык запросов 1С позволяет вставлять конструкцию ВЫБРАТЬ... непосредственно в скобки параметров виртуальной таблицы. Рассмотрим этот метод на примере получения остатков товаров, где тип документа (группа) определяется через родителя конкретного диплома.

Проанализируем пример кода:


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

Как это работает:

  1. Сначала выполняется вложенный запрос к таблице справочника ТипыДокументов.
  2. По условию Т.Ссылка = ЗНАЧЕНИЕ(...) находится конкретный предопределенный элемент.
  3. Из найденной записи извлекается поле Родитель.
  4. Полученное значение (ссылка на группу) передается в условие В основного фильтра виртуальной таблицы.

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

Если задача стоит шире — получить данные не только по прямому родителю, но и по всей ветке иерархии, в которую входит элемент, логика несколько меняется. Однако стоит помнить, что В ИЕРАРХИИ работает со ссылкой. Если вы укажете сам элемент, система найдет только его и его подчиненных (если они есть). Чтобы найти "соседей" по группе, нам все равно нужно сначала получить родителя.

Рассмотрим ситуацию, когда нам нужны все элементы, входящие в ту же группу, что и наш "Диплом":


// Фильтрация по иерархии родителя
ТипДокумента В ИЕРАРХИИ
    (ВЫБРАТЬ
        Т.Родитель
    ИЗ
        Справочник.ТипыДокументов КАК Т
    ГДЕ
        Т.Ссылка = ЗНАЧЕНИЕ(Справочник.ТипыДокументов.Диплом))

В этом случае СУБД сначала определит родителя, а затем выполнит эффективный поиск по всей ветке этой группы.

Проблема "плавающей" иерархии в 1С 8.3

Важно помнить о техническом нюансе современных версий платформы. Начиная с версии 8.3, предопределенные элементы перестали быть "жестко" закрепленными в метаданных. Теперь пользователь в режиме "1С:Предприятие" может изменить родителя предопределенного элемента, если это не ограничено правами доступа или программно.

Чем это грозит:

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

Производительность: Параметры виртуальной таблицы против секции ГДЕ

Выясним причину, почему мы стараемся прописать условие именно в параметрах виртуальной таблицы, а не после слова ГДЕ.

Когда условие (включая наш подзапрос с родителем) находится внутри параметров (например, в Остатки(...)), СУБД накладывает фильтр в момент первичного чтения данных и расчета итогов. Это значительно сокращает объем обрабатываемых данных.

Если же написать:

ВЫБРАТЬ ... ИЗ Регистр.Остатки() КАК Т ГДЕ Т.ТипДокумента = ...

Система сначала получит все остатки по всем типам документов, а уже потом отсечет лишние. На больших базах это может привести к катастрофическому падению производительности.

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

При использовании ВЫРАЗИТЬ (как предлагалось в некоторых сообщениях на форумах) нужно быть осторожным. Если вы попытаетесь выразить родителя, который является корнем справочника, вы можете получить NULL.

Проанализируем безопасный способ обращения:


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

Этот подход гарантирует, что в параметры виртуальной таблицы не попадет неопределенное значение, которое может привести к некорректной выборке.

Резюме

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

← На главную