Как правильно настроить запрос в СКД для получения данных из конкретной папки справочника

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

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

Анализ исходной проблемы

Рассмотрим ситуацию: нам необходимо получить срез последних цен номенклатуры из регистра сведений ЦеныПоставщиков, но только для тех контрагентов, которые находятся в определенной папке (например, в группе "Поставщики").

Типичный ошибочный запрос выглядит следующим образом:


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

Разберем, почему такой подход часто не дает результата или работает нестабильно. Во-первых, условие Контрагенты.Родитель = &Поставщики находит только тех контрагентов, которые лежат непосредственно в указанной папке. Если внутри "Поставщиков" есть подпапки (например, "Оптовые" и "Розничные"), то элементы в них не попадут в выборку. Во-вторых, ключевым моментом является то, что именно передается в параметр &Поставщики.

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

Проанализируем работу оператора В ИЕРАРХИИ. В отличие от простого равенства, этот оператор проверяет вхождение элемента во всю ветку дерева справочника, начиная с указанного узла. Это позволяет захватить все вложенные подпапки и элементы.

Правильное условие в секции ГДЕ должно выглядеть так:


ГДЕ
    Контрагенты.Ссылка В ИЕРАРХИИ (&Поставщики)
    И Контрагенты.ЭтоГруппа = ЛОЖЬ

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

Решение 2: Передача ссылки вместо строки

Выясним причину, по которой отчет может оставаться пустым даже при использовании правильного оператора. Часто это происходит из-за путаницы типов данных. Если в параметр &Поставщики передается строка "Поставщики" (наименование), а не ссылка на элемент справочника, запрос не найдет совпадений.

Рассмотрим, как правильно установить параметр в коде программного вызова или в настройках СКД:

  1. В настройках СКД: На закладке "Параметры" убедитесь, что тип параметра Поставщики установлен как СправочникСсылка.Контрагенты.
  2. В программном коде: Никогда не передавайте строковое значение. Сначала найдите ссылку на нужную группу.

Пример правильной установки параметра:


// Находим ссылку на папку
ГруппаПоставщики = Справочники.Контрагенты.НайтиПоНаименованию("Поставщики");

// Устанавливаем параметр в схеме компоновки или запросе
Запрос.УстановитьПараметр("Поставщики", ГруппаПоставщики);

Хотя поиск по наименованию НайтиПоНаименованию допустим в простых задачах, для надежности рекомендуется использовать Предопределенные элементы, если структура справочника заложена на этапе проектирования системы.

Решение 3: Оптимизация работы с виртуальными таблицами

Проанализируем структуру запроса с точки зрения производительности. В исходном примере фильтрация происходит в секции ГДЕ. Это означает, что система сначала выберет все записи из регистра СрезПоследних, соединит их со справочником и только потом "отрежет" лишнее. На больших базах это приведет к значительным задержкам.

Правильнее передавать условия фильтрации напрямую в параметры виртуальной таблицы. Это позволит СУБД отобрать данные на самом раннем этапе.

Оптимизированный текст запроса:


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

Нюансы ЛЕВОГО СОЕДИНЕНИЯ в СКД

Рассмотрим еще один важный момент. В исходном сообщении использовалось ЛЕВОЕ СОЕДИНЕНИЕ. Если ваша цель — вывести список всех поставщиков из папки, даже тех, по которым нет зарегистрированных цен, используйте именно левое соединение. Однако помните: если вы наложите условие на поле из правой таблицы (например, ЦеныПоставщиков.Цена > 0) в секции ГДЕ, ваше соединение автоматически превратится во внутреннее.

Для сохранения логики левого соединения при работе в СКД:

Итоги и рекомендации

Подводя итоги, для корректной работы отчета по папке в СКД необходимо выполнить три условия:

  1. Использовать оператор В ИЕРАРХИИ для учета вложенных папок.
  2. Следить за тем, чтобы в параметр передавалась Ссылка, а не текстовое название папки.
  3. По возможности выносить условия фильтрации в параметры виртуальных таблиц для повышения скорости работы отчета.

Соблюдение этих правил позволит вам создавать быстрые и надежные отчеты, которые всегда возвращают ожидаемые данные.

← На главную