1с получить дерево в запросе

Обновлено: 07.07.2024

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

В данном разделе показаны примеры решения типовых задач при работе с иерархическими справочниками.

Получение элементов иерархического справочника, находящихся в подчинении заданной группы

Для получения подчиненных элементов иерархического справочника в языке запросов предусмотрена конструкция В ИЕРАРХИИ. Пример использования В ИЕРАРХИИ:

ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура

ГДЕ
Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)

В данном примере будут получены все записи справочника Номенклатура, находящиеся в группе &Группа, включая ее саму, ее подчиненные группы и элементы, принадлежащие подчиненным группам.

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

ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура

ГДЕ
Номенклатура.Родитель = &Группа

Такой запрос выберет группы и элементы, находящиеся в подчинении группы со ссылкой &Группа.

Проверка наличия подчиненных элементов у элемента справочника

Для проверки наличия подчиненных записей элемента справочника можно пользоваться запросом, аналогичным представленному:

ВЫБРАТЬ ПЕРВЫЕ 1
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Родитель = &Родитель

В данном примере ссылка элемента, для которого необходимо проверить наличие дочерних элементов, записывается в параметр запроса "Родитель". После выполнения такого запроса необходимо проверить результат на пустоту. Если результат не пустой, то подчиненные записи есть. Иначе - нет. Пример:

Если Запрос.Выполнить().Пустой() Тогда
Сообщить("Зписей нет");
Иначе
Сообщить("Записи есть");
КонецЕсли;

Получение всех родителей элемента

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

Запрос = Новый Запрос("ВЫБРАТЬ
| Номенклатура.Родитель,
| Номенклатура.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|
|ГДЕ
| Номенклатура.Ссылка = &ТекущийЭлементНоменклатуры";

Пока Истина Цикл
Запрос.УстановитьПараметр("ТекущийЭлементНоменклатуры", ТекущийЭлементНоменклатуры);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
ТекущийЭлементНоменклатуры = Выборка[НомерКолонки];
Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
Прервать;
Иначе
Сообщить(ТекущийЭлементНоменклатуры);
КонецЕсли;
КонецЦикла;

Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
Прервать;
КонецЕсли;
КонецЦикла;

Если число уровней в справочнике ограничено и невелико, то возможно получение всех родителей одним запросом без цикла.

Вывод иерархического справочника в отчет

Для вывода иерархического справочника в отчет с сохранением иерархии необходимо пользоваться запросом аналогичным следующему:

ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
Наименование ИЕРАРХИЯ

Данный запрос выбирает все записи из справочника и производит упорядочивание по иерархии. Результат будет упорядочен по наименованию, с учетом иерархии.

Для того чтобы группы справочника размещались выше элементов необходимо в данном запросе заменить предложение УПОРЯДОЧИТЬ ПО на следующее:

УПОРЯДОЧИТЬ ПО
Номенклатура.ЭтоГруппа ИЕРАРХИЯ,
Наименование

Результат по-прежнему будет упорядочен по иерархии, однако группы будут располагаться выше элементов.

Возможна также замена предложения УПОРЯДОЧИТЬ ПО на предложение АВТОУПОРЯДОЧИВАНИЕ. В этом случае результат будет упорядочен в соответствии с настройками справочника, т.е. если в справочнике указано, что группы должны располагаться выше элементов, то они будут расположены выше.

Получить иерархическую структуру справочника также возможно и при помощи итогов.

ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена

ИЗ Справочник.Номенклатура КАК Номенклатура

ГДЕ
(Номенклатура.ЭтоГруппа = ЛОЖЬ)

УПОРЯДОЧИТЬ ПО Наименование

ИТОГИ ПО Номенклатура.Ссылка ТОЛЬКО ИЕРАРХИЯ

Получение итогов по иерархии

Для получения итогов по иерархии в запросе необходимо в предложении ИТОГИ ПО указать ключевое слово ИЕРАРХИЯ после указания поля, по которому будет рассчитываться итоги. Пример отчета "Обороты номенклатуры" с получением итогов по иерархии:

ВЫБРАТЬ
УчетНоменклатурыОбороты.Номенклатура КАК Номенклатура,
УчетНоменклатурыОбороты.Номенклатура.Представление,
УчетНоменклатурыОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
РегистрНакопления.УчетНоменклатуры.Обороты КАК УчетНоменклатурыОбороты
ИТОГИ СУММА(КоличествоОборот) ПО
Номенклатура ИЕРАРХИЯ

В результате данного запроса будут рассчитаны итоги не только для каждой номенклатуры, но и для групп, к которым принадлежит та или иная номенклатура.

В случае, когда не нужны итоги по элементам, а нужны итоги только по группам, нам необходимо использовать в итогах конструкцию ТОЛЬКО ИЕРАРХИЯ. Пример:

ВЫБРАТЬ
УчетНоменклатурыОбороты.Номенклатура КАК Номенклатура,
УчетНоменклатурыОбороты.Номенклатура.Представление,
УчетНоменклатурыОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
РегистрНакопления.УчетНоменклатуры.Обороты КАК УчетНоменклатурыОбороты
ИТОГИ СУММА(КоличествоОборот) ПО
Номенклатура ТОЛЬКО ИЕРАРХИЯ

В результате данного запроса будут итоговые записи только для групп номенклатуры.

Распечатать

17 правил для составления оптимального ЗАПРОСа к данным базы 1С  42
Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос . Создается этот объект вызовом конструкции Новый Запрос . Запрос удобно использовать, когда требуется получ 1C и Google Maps  20
была поставлена задача отображения на географической карте медицинских учреждений. После обзора предлагаемых решений был выбран сервис google. Но так же подобного рода подход будет работать и с картами сервиса yandex. Во время решения задачи было реш 1С 7.x : Как получить курсы валют с сайта НБУ http://www.bank.gov.ua/ за любую дату ?  6
Функция ПолучитьТаблицуКурсовНБУ(ДатаКурса, Ежедневно = 1) // если в качестве второго параметра указать число отличное от 1 - получем валюты, которые котируются на ежемесячной основе Перем Reader, Url, Точки, HtmlTab, Строк, Р, НомСтроки, НомЯче COM-подключение к базе 7.7 из 8.2 1С  6
Если код выполняется на стороне клиента, то необходимо наличие базы 7.7 на локальной машине. Пример (На форме объекта присутствует реквизит Таблица(ТаблицаЗначений)): НаКлиенте Процедура Загрузки() ПутьКБазе=" D:ВашаБаза1с77" ; Пользователь= Cодержимое указанного ниже веб-сайта в этом приложении блокируется. Aboutsecurity_1cv8c.exe  1
Проблема: После обновления на 1С:Бухгалтерию предприятия 3-й версии, при нажатии на закладку командного интерфейса 1С:предприятие, выскакивает ошибка: Aboutsecurity_1cv8c.exe или Aboutsecurity_1cv8.exe «Содержимое указанного ниже веб-узла в э Посмотреть все результаты поиска похожих

Еще в этой же категории

Значения NULL ( ЕСТЬ NULL и ЕСТЬNULL())  48
NULL – отсутствующие значения. Не путать с нулевым значением! NULL – это не число, не равно пробелу, пустой ссылке, Неопределено. NULL – типообразующее значение, т.е. есть тип NULL и единственное значение этого типа. NULL значения появляются в 17 правил для составления оптимального ЗАПРОСа к данным базы 1С  42
Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос . Создается этот объект вызовом конструкции Новый Запрос . Запрос удобно использовать, когда требуется получ Нарастающий итог в запросе  22
Необходимо использовать левое соединение таблицы с самой собой. ВЫБРАТЬ Обороты.Период, Обороты.Номенклатура, Обороты.Количество ПОМЕСТИТЬ ВТдвижения ИЗ РегистрНакопления.Обороты КАК Обороты ; //////////////////////////////////////////////// Полезные сведения о языке запросов 1С 8.х  22
В статье приведены полезные приемы при работе с запросами 1С v.8.2, а также сведения, которые не так хорошо известны о языке запросов. Я не стремлюсь дать полное описание языка запросов, а хочу остановиться лишь на некоторых моментах, которые для ко Оператор ПОДОБНО  18
ПОДОБНО - Оператор проверки строки на подобие шаблону. Аналог LIKE в SQL. Оператор ПОДОБНО позволяет сравнить значение выражения, указанного слева от него, со строкой шаблона, указанной справа. Значение выражения должно иметь тип строка. Если з Посмотреть все в категории Запросы

Здравствуйте!
Суть вопроса такова: есть РС "Подчинение" (периодический) с измерениями "Оборудование" (Спр. Оборудование) и "Родитель" (Спр. Оборудование). Таким образом хранится история перемещения оборудования с иерархией друг к другу.
Период | Оборудование | Родитель
06.08.2014 | Оборудование_1 |
06.08.2014 | Оборудование_2 |
06.08.2014 | Оборудование_3 |
06.08.2014 | Оборудование_4 |
06.08.2014 | Оборудование_5 |
06.08.2014 | Оборудование_6 |
07.08.2014 | Оборудование_2 | Оборудование_1
07.08.2014 | Оборудование_5 | Оборудование_4
07.08.2014 | Оборудование_6 | Оборудование_5
08.08.2014 | Оборудование_6 |
09.08.2014 | Оборудование_5 | Оборудование_6
09.08.2014 | Оборудование_4 | Оборудование_5
09.08.2014 | Оборудование_2 | Оборудование_3
09.08.2014 | Оборудование_1 | Оборудование_2

Т.е. на 10.08.2014 будет такая картина:
Оборудование_3
__Оборудование_2
____Оборудование_1
Оборудование_6
__Оборудование_5
____Оборудование_4

Вопрос 1 : Как запросом (не в СКД!) получить такое дерево.

Вопрос 2 : Как отловить зацикливание, если попытаться добавить еще одну запись
09.08.2014 | Оборудование_6 | Оборудование_4

(1) MCitrus, не совсем понятно, как построена картина на 10.08.2014 и что она означает. (4) PetroP, чтобы не описывать как построена иерархия, прикрепил выгрузку конфигурации. А нужно это для того, чтобы видеть распределение оборудования в определенный момент времени. В данном случае: как было распределено оборудование на 07.08, как на 08.08 и т.д.

(5) MCitrus, уточняющие вопросы:
1) а максимальное число уровней в иерархии известно? или чем либо ограничено?
2) если дерево нужно построить запросом, то нужно буквально дерево значений получить на выходе из запроса, либо плоскую таблицу, имеющую вид дерева. Дело в том, что дерево значений на выходе запроса можно получить только через выражение "итоги по", а там нужно будет точно назвать уровни, по которым будет делаться группировка.

В любом случае посмотрите статьи: Заметочки про 1С:Предприятие 8 (редакция 22.06.2012) - как построить дерево запросом и Уровни, глубина, прародители, циклы и аналоги запросом - как найти зацикленность запросом (Пример 4). Если про зацикленность покажется слишком сложным, могу адаптировать функцию к вашему случаю - там достаточно переписать "пролог". Но тогда уточните, что хотите видеть на выходе: текст запроса или готовую таблицу с "подозрительными" дугами или просто Да/Нет зацикленности.

(6) ildarovich, максимальное число уровней заранее неизвестно. Изначально было 2, но, как показала практика, может дойти и до 6. Статьи прочитал, спасибо огромное. Если сам "пролог" не осилю, тогда обращусь за помощью))

(2) MCitrus,
запросом рекурсию не получишь.
Запросом, можно вытащить фиксированное количество таблиц, и соединить их по нужным критериям.
Типа, в одной выборке берешь остатки на 10, во второй на 9, в третъей на 8.
И соединяешь таблицы по родителю.
Соответственно и зацикливания в запросе быть не может, т.к заранее все известно.

А так, чтобы одна таблица порождала другую, это можно сделать лишь написав рекурсивную функцию.

Сдается мне, что реквизит "Родитель" нужно сделать ресурсом. Измерением оставить только "Оборудование". Как-то это будет логичнее и правильнее. Два родителя ведь быть не может (одновременно, учитывая периодичность). Тогда запрос сводится к получению среза последних. Дерево же строить уже в коде, как написал (3) Boneman, зачем вам сложности с хитрыми запросами? (7) omut, про ресурс вы четко подметили. Спасибо. Дело в том что дерево нужно построить именно запросом (не в коде). Вот тут-то я застопорился.. (9) MCitrus, Одним запросом дерево не построить, но выпопление этого запроса ножно сделать несколько раз пока не будет выпоплено некое условие, например больше ни чего не найдено.
Была бы база перед глазами я бы вам точно расписал что да как. (9) MCitrus, если не трудно, скажите, пожалуйста, почему именно запросом и никак иначе. Выше уже коллеги неоднократно и правильно заметили, что запрос - он о другом. Он таблицы формирует. Дерево же только через рекурсию или - в крайнем случае - когда уровень вложенности заранее известен. Увы, каждому свое и дереву не запрос :) (11) omut, :-))) это я знаю)) Такой вопрос неоднократно поднимался в дебрях инета, ответа на него мне найти не удалось. Я поднял тему в надежде, что кто-то уже победил эту "хотелку" и может поделиться опытом.
Значит строить деревья буду по советам коллег))

(12) MCitrus, вот еще какое соображение пришло в голову.
Требование сделать обработку данных запросом обычно объясняется желанием решить задачу средствами СУБД.
Но СУБД не выдает результат в виде дерева. В T-SQL (в который транслируется запрос) в операторе select нет выражения похожего на "итоги по". Выражение "итоги по" реализуется не в СУБД, а в 1С уже после получения таблицы из СУБД. То есть "итоги по" кажутся внесенными в язык запросов "зародышами" построителя отчета и далее СКД. А значит, не должно быть предубеждения против использования для построения дерева внешних по отношению к запросу средств - это те же "итоги по".

Если все же упереться (почти невозможное всегда интересно), то пока приходит в голову единственное решение:
В информационной базе должен иметься иерархический справочник с разветвленной структурой, который может включить все возможные варианты переподчинения оборудования.
Обычно самой разветвленной структурой обладает справочник номенклатура, но можно завести специальный справочник-скелет "пространство для иерархий". Затем одним запросом определить положение оборудование в узлах иерархии (это можно сделать). Каждому элементу будет соответствовать полный путь от корня типа 1/1/2/1/3/1 или 1/2/3/1, где между разделителями - номера узлов в рамках одного подчинения. По этому пути связать оборудование с элементами справочника "пространство для иерархий". И использовать "итоги по" узлам этого "скелета".

Если ограничить число уровней каким-либо разумным числом, а также ограничить число единиц оборудования в рамках одного подчинения, то справочник-"скелет" легко генерируется.

Не знаю, насколько этот совет применим именно к вашему случаю. Записал его здесь, чтобы не держать в голове эту задачу.

Эту статью я хочу написать в виде конкретных примеров по работе с деревом значений в 1С 8.3 и 8.2.

Дерево значений представляет из себя некую структуру с иерархией. У каждой строки дерева значений может быть сколько угодно подчиненных строк.

Создание дерева значений в 1С

Вот пример процедуры:

Здесь стоит особенно обратить внимание на два фактора, без которых дерево не сформируется:

Если не указать правильно вид обхода результата выборки по запросу, то мы получим обычную таблицу значений.

Результат вывода данного запроса 1С дерево значений на управляемую форму выглядит следующим образом:

Если вы только начинаете программировать в 1С или просто хотите систематизировать свои знания - попробуйте Школу программирования 1С нашего друга Владимира Милькина. Пошаговые и понятные уроки даже для новичка с поддержкой учителя.
Попробуйте бесплатно по ссылке >>

дерево значений 1с 8.3 на управляемой форме

Теперь, на мой взгляд, самое интересное. Как организовать обход дерева значений, если мы заранее не знаем, сколько уровней в нем.

Обход дерева значений с помощью рекурсии

В основном обход дерева в 1С делается с помощью рекурсии. Даже когда известно, сколько уровней в нем. С рекурсией это проще, всего около шести строк:

обработка

Пример данной обработки для управляемых форм можно скачать по ссылке. С помощью аналогичного кода 1С возможно преобразовать дерево значений в таблицу значений.

При обходе дерева Вы можете выполнять различные действия над ним. Например:

  • подсчет итогов по группам;
  • раскраску строк по нужным параметрам;
  • удалять ненужные строки;
  • можно делать различные отборы;
  • и так далее.

Читайте также: