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