Как правильно формировать запрос по иерархическому справочнику в дерево?
Есть справочник (Тест1), обычный иерархический(иерархия групп и элементов, отображение групп сверху – отключено, но это не важно), например, с такой структурой, отображаемой в форме списка (в режиме дерева, упорядочен по коду):
Г1
| — Э1
| — Г2
| | — Э21
| | — Э22
| — Э3
Хочу запросом получить его в виде дерева значений (ДЗ), но никак не получается
Пишу запрос
ВЫБРАТЬ Тест1.Ссылка КАК Ссылка ИЗ Справочник.Тест1 КАК Тест1 ГДЕ Тест1.ЭтоГруппа = ЛОЖЬ УПОРЯДОЧИТЬ ПО Тест1.Код ИТОГИ ПО Ссылка ИЕРАРХИЯ
Когда результат выгружается в ДЗ так:
ДЗ = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Получаю такую иерархию строк в ДЗ
Г1
| — Э1
| | — Э1*
| — Г2
| | — Э21
| | | — Э21*
| | — Э22
| | | — Э22*
| — Э3
| | — Э3*
В результате лишние элементы, помеченные *
А когда результат выгружается в ДЗ так:
ДЗ = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
Г1
Э1**
| — Э1*
Г2**
Э21**
| — Э21*
Э22**
| — Э22*
Э3**
| — Э3*
В результате лишние элементы, помеченные *, а элементы Э1**, Э3**, Э21**, Э22** не на своём месте
Если заменяю в запросе на
ИТОГИ ПО Ссылка ТОЛЬКО ИЕРАРХИЯ
Тогда при выгрузки по иерархии, получаю такую иерархию строк в ДЗ
Г1
| — Г1*
| | — Э1**
| | — Э3**
| — Г2
| | — Э21
| | — Э22
В результате лишние элементы, помеченные *, а элементы Э1**, Э3** не на своём месте (относительно позиции группы Г2)
При выгрузки в ДЗ по группировкам без иерархии
Г1*
Г1
| — Э1
| — Э3
Г2**
| — Э21
| — Э22
В результате лишний элемент Г1 помеченный *, а элемент Г2 ** не на своём месте
Вопрос, как надо сформировать запрос, чтобы получить реальную структуру справочника в ДЗ?
Ниже прилагается тестовая база (обычное приложение 8.3.10):
ВЫБРАТЬ Тест1.Ссылка КАК Ссылка ИЗ Справочник.Тест1 КАК Тест1 УПОРЯДОЧИТЬ ПО Тест1.Ссылка ИЕРАРХИЯ АВТОУПОРЯДОЧИВАНИЕ
ДЗ = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
ИТОГИ ПО Ссылка ТОЛЬКО ИЕРАРХИЯ
(9) В сабже рассмотрены оба варианта . Но для меня это всё не логично. Логично было бы так:
«ИЕРАРХИЯ» — должна была бы вывести структуру как есть: элементы и группы (как это делает СКД)
«ТОЛЬКО ИЕРРАХИЯ» должна была бы вывести структуру групп без концевых элементов (как это делает СКД)!
(10) По результатам запроса Иерархии мы получаем ту линейную таблицу, о которой Вы говорили, со значениями родителя каждой строки.
И мы формируем новую иерархию через код — получается одно.
А СКД получая ту же линейную таблицу формирует её по своим правилам — получается другое.
(13)Во-первых, о линейной таблице я не говорил — мне нужна структура иерархического справочника как она есть — но в виде дерева значений!
Во-вторых, поведение обычного запроса, для меня, совершенно не логично и не корректно, в отличии от СКД.
В-третьих, должно было быть — одинаково (как в СКД) при данной тривиальной постановке задачи и настройки! Налицо — некорректная работа в платформе обычных запросов, при обработке иерархических данных!
(9)Вот это в сабже не видели:
Если заменяю в запросе на
ИТОГИ ПО
Ссылка ТОЛЬКО ИЕРАРХИЯ
ВЫБРАТЬ Тест1.Ссылка КАК Ссылка ИЗ Справочник.Тест1 КАК Тест1 УПОРЯДОЧИТЬ ПО Тест1.Ссылка ИЕРАРХИЯ АВТОУПОРЯДОЧИВАНИЕ
ДЗ = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
С этим фильтром иерархия не получается 🙁
Работает и такой вариант тоже (вместо упорядочивания по коду — можно указать другой реквизит — как у меня на самом деле в рабочем варианте)
ВЫБРАТЬ Тест1.Ссылка КАК Ссылка ИЗ Справочник.Тест1 КАК Тест1 УПОРЯДОЧИТЬ ПО Тест1.Код ИЕРАРХИЯ
Саммое интерсеное, что про такой вариант конструкции я даже не знал до сегодняшнего дня — пока не стал копаться в доках
УПОРЯДОЧИТЬ ПО Тест1.Код ИЕРАРХИЯ
Но, всё равно, считаю, что разработчики платформы 1С8 тут с иерархической выборкой перемудрили 😉
Но всё равно, спасибо Вам, Олег, за решение!
Запрос = Новый Запрос; Запрос.Текст = ЭлементыФормы.ТекстЗапроса.ПолучитьТекст(); РезультатЗапроса = Запрос.Выполнить(); Если ПоГруппировкам=0 Тогда дз = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам); Иначе дз = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией); КонецЕсли; ЭлементыФормы.ДЗ.СоздатьКолонки();
(4)И что? Там запрос отработает правильно? У меня этот запрос никак не связан с интерактивной работой и отчётами, мне что — прикручивать в серверный бакэнд СКД чтобы просто корректно выполнить выборку из справочника? Да мне проще вручную собрать это ДЗ из линейной таблицы по родителю.
(5) Ну, запросы — они немножко о другом, вообще-то.
А отработает правильно, куда же он денется.
Если проще вручную собрать — собирайте вручную.
(6)Спасибо. В обработке. Выгрузка через СКД работает (единственное — не хватало условия в запросе «ГДЕ Тест1.ЭтоГруппа = ЛОЖЬ», которое в моём сабже почему-то тоже пропало (хотя я его туда помещал). Но, такой подход требует создания схемы СКД — что несколько усложняет процесс. Но, может Вы правы — лучше вместо запроса прикрутить СКД для данного случая хотя бы. Другом решением было бы в самом первом варианте запроса попросту удалить из ДЗ нижние листья дерева — без них тоже будет правильный результат (для данного примера).
Но у меня тут больше философский был вопрос — почему обычный запрос корректно не отрабатывает? Это ошибка платформы? Мне, кажется, давным давно (ещё до появления СКД), у меня нормально такие запросы отрабатывали, просто с тех пор почти не сталкивался с такими запросами вне отчетов. Ведь что может быть проще — когда выбраны итоги «ИЕРАРХИЯ» — выгрузить в ДЗ физическую иерархию таблицы справочника! А сейчас — прям одни глюки при выборке, которые я совершенно не могу понять — чем они обоснованы!
А на практике — использование СКД ещё потребует программного создания «схемы компоновки» для каждого такого запроса — что на СКД очень не удобно делать!
Приложил к сабжу тестовую базу (и включил туда обе обработки: через запрос и через скд) — может кто-нибудь разъяснит, почем через запрос работает криво, а через СКД — корректно (хотя чаще бывает как раз наоборот)!
Вот тут 1С пишет про иерархию в запросах, но ведь не работает так как написано (хотя там в статье и не приведены примеры результатов работы).
Дерево сформировать то просто а вот вывести из такой структуры данных в форме в дерево значений можно быстро?
Чтобы картинка была такой к примеру:
Выбрали справочник из списка, его наименование подставилось в запрос, запрос выполнили и загрузили иерархию справочника в дерево на форме. Потом передвигаясь в дереве по пакам при выборе папки отрисовывается второй элемент — таблица значений элементами справочника находящегося в выбранной папке и т.д.
Вот это дерево (из предыдущего поста 18) сделано на основании элементарного запроса без всяких иерархий и группировок
Запрос.Текст ;
Запрос.Текст = СтрЗаменить(Запрос.Текст,»Номенклатура», ИмяСправочника);
но потом пришлось рекурсивную процедуру писать аж из 8 строк,, а кое где пишут что можно сделать проще через группировки в запросе и просто загрузив данные в элемент формы — сколько не пробовал нек получается..
Есть примеры?
Источник
Иерархический справочник в дерево значений
Перебрал уже все возможные варианты с Иерархия, упорядочить по иерархия, Итоги по Иерархия, обход по группировкам с иерархией и прочее.
Но нужный результат пока не получил, а время уже поджимает..
мне кажется, тебе должно помочь вот это
ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений (DataCompositionResultValueCollectionOutputProcessor)
Вывести (Output)
Синтаксис:
Вывести(, )
Параметры:
(обязательный)
Тип: ПроцессорКомпоновкиДанных.
Процессор компоновки данных, из которого будут получаться элементы результата.
(необязательный)
Тип: Булево.
Указывает, может ли пользователь прервать вывод при помощи комбинации клавиш Ctrl + Break.
Значение по умолчанию: Ложь.
Возвращаемое значение:
Тип: ТаблицаЗначений, ДеревоЗначений.
Описание:
Выводит весь результат в объект.
При этом автоматически исполняется метод НачатьВывод, перебираются все элементы процессора компоновки и выводятся в результат. После чего исполняется метод ЗакончитьВывод, результат которого возвращается данным методом.
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| ЛОЖЬ КАК Пометка,
| Подразделения.Ссылка КАК Ссылка,
| Подразделения.Владелец КАК Организация
|ИЗ
| Справочник.Подразделения КАК Подразделения
|
|УПОРЯДОЧИТЬ ПО
| Организация,
| Ссылка ИЕРАРХИЯ
|АВТОУПОРЯДОЧИВАНИЕ»;
Источник
1с запрос дерево иерархического справочника
Иногда нужно получить дерево групп справочника запросом.
Для этого удобно использовать итоги по иерархии.
Допустим у нас есть дерево:
Пусть мы выполнили какой-то запрос и получили, что нам походят элементы из некоторого списка &Список, например Д и И.
Варианты отображения иерархии
Существуют два варианта отображения иерархии, в которую попадают элементы из списка Список:
Иерархия с подчиненными
Для отображения иерархии в случае с подчиненными, нам достаточно получить родителей всех элементов, расположенных на нижнем уровне иерархии и сгруппировать их по иерархии:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Т1.Ссылка.Родитель КАК Ссылка
ИЗ
Справочник.Задача КАК Т1
ГДЕ
Т1.Ссылка В ИЕРАРХИИ(&Ссылки) И 0 В (ВЫБРАТЬ Количество(*) ИЗ Справочник.Задача КАК Т2 ГДЕ Т1.Ссылка=Т2.Родитель)
ИТОГИ ПО
Ссылка ТОЛЬКО ИЕРАРХИЯ
Для иерархии групп и элементов:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Т1.Ссылка.Родитель КАК Ссылка
ИЗ
Справочник.Задача КАК Т1
ГДЕ
Т1.Ссылка В ИЕРАРХИИ(&Ссылки) И Т1.ЭтоГруппа=ложь
ИТОГИ ПО
Ссылка ТОЛЬКО ИЕРАРХИЯ
Иерархия без подчиненных
В данном случае сложнее. 1С неправильно группирует по иерархии, она плодит дубли.
Код запроса будет таким:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Т1.Ссылка.Родитель КАК Ссылка
ИЗ
Справочник.Задача КАК Т1
ГДЕ
Т1.Ссылка В (&Ссылки)
ИТОГИ ПО
Ссылка ТОЛЬКО ИЕРАРХИЯ
Полученное дерево нужно будет обработать функцией для удаления лишних дублей:
Функция обУбратьОшибкиИтоговПоИерархии(Строки, Поле cb">Ссылка", Родитель=Неопределено) Экспорт //Убираем все элементы, равные текущему Всего=Строки.Количество(); Для Инд=1 По Всего Цикл Стр=Строки[Всего-Инд]; Зн=Стр[Поле]; Если Родитель<>Неопределено И Зн=Родитель Тогда Строки.Удалить(Стр); Иначе обУбратьОшибкиИтоговПоИерархии(Стр.Строки, Поле, Зн); КонецЕсли; КонецЦикла; КонецФункции . ВычСправочникДерево=Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией); обУбратьОшибкиИтоговПоИерархии(ВычСправочникДерево.Строки);
Источник