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