Как найти родителя в запросе

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

Если количество уровней фиксированное, то через точку можно получить родительский элемент любого уровня.

РодительСсылка = СправочникСсылка.Родитель.Родитель.Родитель; 

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

Определить самого верхнего родителя

Универсальную функцию для определения самого верхнего родителя элемента можно реализовать с помощью встроенного языка программирования. Функции на вход подаётся ссылка на элемент иерархического справочника, а возвращается ссылка на самую верхнюю группу.

Функция ПолучитьРодителя(СправочникСсылка)Пока НЕ СправочникСсылка.Родитель.Пустая() Цикл
СправочникСсылка = СправочникСсылка.Родитель;
КонецЦикла;Возврат СправочникСсылка;КонецФункции

Определить самого верхнего родителя с использованием запроса

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

Функция ПолучитьРодителейЗапросе(СправочникСсылка)

Запрос

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

Запрос

.УстановитьПараметр("Справочник1Ссылка", СправочникСсылка);
Результат = Запрос.Выполнить();Если НЕ Результат.Пустой() Тогда

Выборка

= Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Родитель;КонецЕсли;Возврат Справочники.Справочник1.ПустаяСсылка();КонецФункции

Запросом выбрать верхнего родителя

Я
   dfaa

04.07.11 — 20:30

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

   PR

1 — 04.07.11 — 20:37

(0) Никак, только через иерархическую выборку.

Но проще в цикле IMHO.

   Жан Пердежон

2 — 04.07.11 — 20:40

ВЫБРАТЬ ЗНАЧЕНИЕ(Справочник.ИмяСправочника.ПустаяСсылка)

   dfaa

3 — 04.07.11 — 20:45

(2) да ладно, это я выберу пустую ссылку.

   dfaa

4 — 04.07.11 — 20:46

неужели в запросе не как не получиться ?

   kumena

5 — 04.07.11 — 20:46

(2) так это пустая ссылка, а автору надо элемент самого верхнего уровня.

я писал так, когда времени не было.

Выбор Когда Родитель Значение(справочник.Номенклатура.ПустаяСсылка)

Тогда Ссылка

Иначе

Выбор Когда родитель.родитель …

тогда ссылка.родитель

Конец

а вообще можно написать запрос, но подумать надо

   Лефмихалыч

6 — 04.07.11 — 20:51

(0) зачем именно запросом? Какая религия запрещает рекурсию и циклы?

   dfaa

7 — 04.07.11 — 20:54

(6) да собственно ни какая. Просто хотелось сделать всё запросом, так как номенклатуры больше сотни тысяч, не хотелось бы её гонять в цикле

   PR

8 — 04.07.11 — 20:56

(7) Тогда делай коряво.

Определяй максимальный уровень вложенности и (5).

Кстати, может в свежих 8.2 решили вопрос получения уровня в запросе, тогда может что-то получится придумать в запросе.

   kumena

9 — 04.07.11 — 20:59

«зачем именно запросом? Какая религия запрещает рекурсию и циклы?» — например в компоновку воткнуть.

   Лефмихалыч

10 — 04.07.11 — 21:00

ну, соединение по иерархии не возможно по крайней мере в имеющихся на сегодняшний день платформах

Как-то придется с этим жить

   MikleV

11 — 04.07.11 — 21:10

зато возможно получение результата запроса, в котором на верхнем уровне будет желаемое

   dfaa

12 — 04.07.11 — 21:13

(11) и как его получить ?

   Baker_it

13 — 04.07.11 — 21:22

Ну итоги по иерархии видимо :)

   MikleV

14 — 04.07.11 — 22:19

УПОРЯДОЧИТЬ ПО

   Parti

15 — 04.07.11 — 22:21

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

   ILM

16 — 04.07.11 — 22:29

(0) Делай пакет запрос:

Первый итоги выводит для всех в данной ветке,

Второй отбор где родитель = ЗНАЧЕНИЕ(Спр-к.ЛаЛаЛа.ПустаяСсылка) из (3)

   ILM

17 — 04.07.11 — 22:30

(15) Опередил, пока чай наливал )))

   Лефмихалыч

18 — 04.07.11 — 22:36

(14),(17) пример может покажите?

   Лефмихалыч

19 — 04.07.11 — 22:38

+(18) Во-первых, в пакетном запросе УПОРЯДОЧИТЬ ПО возможно использовать только в купе с ПЕРВЫЕ. А, во-вторых, у меня платформа радостно обрухнула при попытке провернуть этот трюк из брюк

   MikleV

20 — 04.07.11 — 22:38

(18)а я что то говорил про пакетный запрос?

   MikleV

21 — 04.07.11 — 22:39

ВЫБРАТЬ *

ИЗ Т КАК Т

УПОРЯДОЧИТЬ ПО Т.Ссылка ИЕРАРХИЯ

   bazvan

22 — 04.07.11 — 22:40

»    Лефмихалыч

23 — 04.07.11 — 22:41

»    Лефмихалыч

24 — 04.07.11 — 22:43

(21) и дальше чо?

   MikleV

25 — 04.07.11 — 22:56

(24)обход результата запроса

   ILM

26 — 04.07.11 — 22:59

Счас по быстрому не найду, делал типа

ВЫБРАТЬ ПЕРВЫЕ 10000 *

ПОМЕСТИТЬ ТЕМП

ИЗ …

УПОРЯДОЧИТЬ ПО … ИЕРАРХИЯ

ИТОГИ ПО ИЕРАРХИИ

;

ВЫБРАТЬ … ИЗ ТЕМП ГДЕ ТЕМП.Ссылка = ЗНАЧЕНИЕ(…..ПустаяСсылка)

Просто знал, что никогда и 10 тыс не будет в ветке.

   Попытка1С

27 — 04.07.11 — 22:59

Опять… Обсасывали вроде бы месяц назад.

   ILM

28 — 04.07.11 — 23:01

(27) А что делать? Просят раз пососать

   Лефмихалыч

29 — 04.07.11 — 23:02

(25) а, вон оно чо, а я-то думал, что дальше как-то ЗАПРОСОМ ты собрался. Так-то оно рекурсией или циклом и быстрее и читабельнее получится

(26) падает платформа, аргументируя это тем, что «Выход за размерность» или что-то такое. Да и какой понт в этом велосипеде, если проще так:

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

Задача была в том, чтобы родителя верхнего уровня конкретного элемента найтить только запросом. А это всё фигня от лукавого и не серьезно

   ILM

30 — 04.07.11 — 23:05

(29) Рекурсией лучше, но раз люди хотят запросом — зачем им в этом отказывать.

   ПульсЪ

31 — 04.07.11 — 23:07

Функция родительпервогоуровня()

Запрос = Новый Запрос;

   Запрос.Текст = »

   |ВЫБРАТЬ

   |    Контрагенты.Наименование

   |ИЗ

   |    Справочник.Контрагенты КАК Контрагенты

   |ГДЕ

   |    Контрагенты.ЭтоГруппа = &ЭтоГруппа

   |    И Контрагенты.Родитель = &ПустаяСтрока

   |»;

   
   Запрос.УстановитьПараметр(«ЭтоГруппа», Истина);

   Запрос.УстановитьПараметр(«ПустаяСтрока»,Справочники.Контрагенты.НайтиПоКоду(«») );

   Выборка = Запрос.Выполнить().Выбрать();

   Выборка.Следующий();

   возврат Выборка.Наименование

КонецФункции

   ПульсЪ

32 — 04.07.11 — 23:08

а не

   Попытка1С

33 — 04.07.11 — 23:08

   ПульсЪ

34 — 04.07.11 — 23:08

или… все норм

   thezos

35 — 04.07.11 — 23:12

полный кот

   ПульсЪ

36 — 04.07.11 — 23:15

(0) проверил) канает)  пользуйся (31)

   ПульсЪ

37 — 04.07.11 — 23:16

тока нуна что бы в справочнике была папка первого уровня одна) ну или допили чутка

   Jackman

38 — 05.07.11 — 02:55

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    Номенклатура.Ссылка КАК Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура
               |ГДЕ
               |    Номенклатура.Ссылка = &Товар
               |
               |ИТОГИ ПО
               |    Ссылка ТОЛЬКО ИЕРАРХИЯ";
Запрос.УстановитьПараметр("Товар",    Товар);     
ТЗ = Запрос.Выполнить().Выгрузить();

Если ТЗ.Количество()>0 Тогда
    Сообщить(ТЗ[ТЗ.Количество()-1].Ссылка);
Иначе
    Сообщить("упс");
 КонецЕсли;
   Рэйв

39 — 05.07.11 — 07:06

Выбрать

Выбор когда Ссылка.Родитель Есть NULL

     Тогда «Верхний уровень»

     Когда Ссылка.Родитель.Родитель Есть NULL

     Тогда Ссылка.Родитель

     Когда Ссылка.Родитель.Родитель.Родитель Есть NULL

     Тогда Ссылка.Родитель.Родитель

     Когда Ссылка.Родитель.Родитель.Родитель.Родитель Есть NULL

     Тогда Ссылка.Родитель.Родитель.Родитель

….

  

Рэйв

40 — 05.07.11 — 07:09

+

…Конец КАК ВерхнийПапа

естессно:-)

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

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

ВЫБРАТЬ
    Номенклатура.Код, 
    Номенклатура.Наименование КАК Наименование, 
    Номенклатура.ЗакупочнаяЦена 
ИЗ 
    Справочник.Номенклатура КАК Номенклатура
ГДЕ 
    Номенклатура.Ссылка В ИЕРАРХИИ (&Группа) 

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

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

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

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

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

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

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

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

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

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

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

ТекущийЭлементНоменклатуры = ЭлементНоменклатура;

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

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

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

В данном примере в окно служебных сообщений выводятся все родители для ссылки, записанной в переменную ЭлементНоменклатура. В цикле выбирается по пять родителей ссылки.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Поиск:
1С:Предприятие • Иерархия • Справочник • Язык запросов

 0 

   

Распечатать

Как получить запросом «Первый» Родитель элемента справочника

Код 1C v 8.х

  
ВЫБРАТЬ
СотрудникиОрганизаций.Наименование,
ВЫБОР
КОГДА (СотрудникиОрганизаций.ПодразделениеОрганизации.Родитель.Наименование ЕСТЬ NULL ) ТОГДА СотрудникиОрганизаций.ПодразделениеОрганизации.Наименование
КОГДА (СотрудникиОрганизаций.ПодразделениеОрганизации.Родитель.Родитель.Наименование ЕСТЬ NULL ) ТОГДА СотрудникиОрганизаций.ПодразделениеОрганизации.Родитель.Наименование
ИНАЧЕ СотрудникиОрганизаций.ПодразделениеОрганизации.Родитель.Родитель.Наименование
КОНЕЦ КАК Департамент
ИЗ
Справочник.СотрудникиОрганизаций КАК СотрудникиОрганизаций

Содержание:

1.       Простая рекурсивная функция

2.       Запрос в цикле  

1.      Простая рекурсивная функция

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

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

Функция ПолучитьМассивРодителейЭлемента(ЭлементСправочника)

                МассивРодителейЭлемента = Новый Массив;

                Пока ПустоеЗначение(ЭлементСправочника.Родитель) = 0 Цикл

                               МассивРодителейЭлемента.Добавить(ЭлементСправочника.Родитель);                      

                               ЭлементСправочника = ЭлементСправочника.Родитель;

                КонецЦикла

                Возврат МассивРодителейЭлемента;

КонецФункции

Данный метод может использоваться также и для получения всей цепочки документов-оснований списка документов, нужно только подставить вместо элемента справочника нужный нам документ, а вместо родителя проверять на заполненность вариант документа — основания.  

2.      Запрос в цикле

Хотя приведенная выше простая рекурсивная функция компактна и легка в написании, она имеет существенный для производительности недостаток – обращение через точку в цикле. При обращении каждую итерацию к серверу будут получены не только все ненужные реквизиты элемента справочника или документа, но и все табличные части, привязанные к данному элементу, что увеличит нагрузку на сервер и снизит производительность, получая с сервера большое количество ненужных данных. Например, если мы получаем документ-основание реализации, в которой тысяча строк, то все эти будут переданы с сервера на клиент. Нагрузку можно снизить, заменив обращение через точку выполнением запроса в цикле. В этом случае каждую итерацию цикла будем получать хотя бы только нужный нам реквизит. Но запрос в цикле тоже вещь очень плохая, так как инициирует многократное обращение к серверу, увеличивая время, затрачиваемое на работу цикла. Поэтому гораздо лучше не выполнять запрос в цикле, а создавать в цикле текст запроса, затем выполнить запрос с полученным текстом, получив все нужные данные с сервера только один раз. Рассмотрим пример запроса с динамическим формированием текста запроса в зависимости от уровня родителя справочника в 1С:

Функция ПолучитьМассивРодителейЭлемента (ЭлементСправочника)

                МассивРодителейЭлемента = Новый Массив;

                УровеньРодителя = ЭлементСправочника.Уровень();

                ТекстОбъединить = «»;

                ТекстРодительЭлемента = «»;

                ТекстЗапросаВТ = «»;

                Для инд = 1 По УровеньРодителя Цикл

                               ТекстРодительЭлемента= ТекстРодительЭлемента+ «.Родитель»;

                               Если инд<> 1 Тогда

                                               ТекстОбъединить= »

                                               |            

                                               |             ОБЪЕДИНИТЬ ВСЕ

                                               |»;

                               КонецЕсли;

                               ТекстЗапросаВТ= ТекстЗапросаВТ+ ТекстОбъединить+ »

                               |ВЫБРАТЬ

                               |                             Склады» + ТекстРодительЭлемента+ » КАК Родитель

                               |              ИЗ

                               |                             Справочник.Склады КАК Склады

                               |              ГДЕ

                               |                             Склады.Ссылка = &ЭлементСправочника»;

                КонецЦикла;

                Запрос = Новый Запрос;

                Запрос.Текст = »

                |ВЫБРАТЬ

                |             ВТ_СписокРодителей.Родитель КАК Родитель

                |ИЗ

                |             (» + ТекстЗапросаВТ+ «) КАК ВТ_СписокРодителей»;

                Запрос.УстановитьПараметр(«ЭлементСправочника», ЭлементСправочника);

                ВыборкаЗапроса = Запрос.Выполнить().Выбрать();

                Пока Выборка.Следующий() Цикл

                               МассивРодителейЭлемента.Добавить(Выборка.Родитель);

                КонецЦикла;

                Возврат МассивРодителейЭлемента;

КонецФункции

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

Специалист компании «Кодерлайн»

Александр Суворов

Понравилась статья? Поделить с друзьями:
  • Как найти стороны равнобедренного треугольника если известно
  • Как найти площадь трехмерного прямоугольника
  • Как найти сумму всех столбцов в экселе
  • Как найти силу тяги в двигателе машины
  • Как найти площидь фигуры