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

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

При разработке отчетов и обработок в 1С часто возникает ситуация, когда первоначально справочник имел одноуровневую структуру, а затем потребовалось разделить элементы на подгруппы (например, внутри группы «Наша розница» появились папки «Оптовики» и «Розница»). Если в тексте запроса было жестко прописано условие равенства непосредственному родителю, то после реструктуризации справочника вложенные элементы перестают попадать в выборку. Разберем, как правильно составить запрос для отбора данных по всей иерархии группы.

Причина возникновения проблемы

Рассмотрим типовой фрагмент запроса, в котором условие выборки накладывается на прямого родителя элемента:


ИЗ
    РегистрНакопления.Продажи.Обороты(
        &Нач,
        &Кон,
        Регистратор,
        Номенклатура.ВидНоменклатуры <> &Товар
            И Контрагент.Родитель = &НашаРозница) КАК ПродажиОбороты

Выясним причину ошибки: условие Контрагент.Родитель = &НашаРозница проверяет только тех контрагентов, которые лежат непосредственно в корне папки «Наша розница». Если перенести контрагента во вложенную подпапку (например, «Наша розница/Оптовики»), его непосредственным родителем становится новая подгруппа, а равенство условию перестает выполняться. В результате обороты по таким контрагентам исключаются из отчета.

Решение проблемы: использование оператора «В ИЕРАРХИИ»

Для того чтобы запрос выбирал как саму группу, так и все ее вложенные подгруппы и элементы на любой глубине вложенности, в языке запросов 1С предусмотрена конструкция В ИЕРАРХИИ.

Разберем по шагам, как правильно внести изменения:

  1. В параметрах виртуальной таблицы регистра или в секции ГДЕ заменяем условие Контрагент.Родитель = &НашаРозница на конструкцию Контрагент В ИЕРАРХИИ (&НашаРозница).
  2. Обратите внимание: условие следует накладывать напрямую на поле Контрагент, а не через точку Контрагент.Родитель. Это исключает лишнее неявное соединение с таблицей справочника и гарантирует выборку всех уровней дерева.

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


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

Передача параметров в запрос и типичные синтаксические ошибки

Проанализируем установку параметров. При поиске ссылки по коду важно следить за корректным обращением к менеджеру справочника:


// Ошибочный вариант (пропущена точка):
// Запрос.УстановитьПараметр("НашаРозница", Справочники.КонтрагентыНайтиПоКоду("F00000023"));

// Корректный вариант:
ГруппаРозница = Справочники.Контрагенты.НайтиПоКоду("F00000023");
Запрос.УстановитьПараметр("НашаРозница", ГруппаРозница);

Особенности оптимизации и рекомендации

Рассмотрим подробнее важные нюансы работы с иерархией в 1С:

  1. Фильтрация в параметрах виртуальной таблицы: Всегда передавайте условие В ИЕРАРХИИ в параметры виртуальной таблицы регистра (четвертый параметр для таблицы Обороты), а не в общую секцию ГДЕ. Это позволяет СУБД отсечь ненужные записи на этапе расчета итогов, существенно ускоряя выполнение отчета.
  2. Передача коллекций значений: Оператор В ИЕРАРХИИ поддерживает работу со списками. Если вам необходимо выбрать данные сразу по нескольким несвязанным веткам справочника, в параметр можно передать массив или СписокЗначений, содержащий нужные группы.
  3. Проверка найденных ссылок: Метод НайтиПоКоду() в случае отсутствия элемента вернет пустую ссылку (Справочники.Контрагенты.ПустаяСсылка()). Передача пустой ссылки в условие В ИЕРАРХИИ не вызовет исключения, но приведет к получению пустого результата или выборке элементов без иерархии. Перед выполнением запроса рекомендуется проверять результат поиска на ЗначениеЗаполнено().
  4. Отказ от жесткого кодирования (Hardcode): Поиск по коду в коде конфигурации уязвим к человеческому фактору (код могут изменить пользователи, либо может нарушиться уникальность в пределах подчинения). Для ключевых узлов логики надежнее использовать предопределенные элементы (обращаясь к ним через ЗНАЧЕНИЕ(Справочник.Контрагенты.НашаРозница)) либо сохранять ссылки в константах или дополнительных реквизитах.
← На главную