Соединение в запросе, сравнение (В ИЕРАРХИИ)


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

Как вариант можно перебрать родителей через ИЛИ, например так


Номенклатура.Родитель = Номенклатура1.Ссылка
    ИЛИ Номенклатура.Родитель.Родитель = Номенклатура1.Ссылка
    ИЛИ Номенклатура.Родитель.Родитель.Родитель = Номенклатура1.Ссылка
    ИЛИ Номенклатура.Родитель.Родитель.Родитель.Родитель = Номенклатура1.Ссылка


Только здесь глубина родителей конечна, если же непонятно какую глубину имеет справочник, то можно это решить так
выгрузить родителей вообще в таблицу значений в две колонки,
в одной родитель, а во второй все возможные его родители (по количеству родителей количество строк в таблице значений
полученную таблицу использовать для соедениения

Это мое первое сочинение для Инфостарта

В запросе, в соединении нельзя указать например:  ЛЕВОЕ СОЕДИНЕНИЕ ....... Ссылка В ИЕРАРХИИ(ТЗ.Ссылка)

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

идея в том что бы подготовить такую таблицу значений, где была бы информация



Первая колонка      Вторая колонка

Родитель                 Родитель.Родитель

Родитель                 Родитель.Родитель.Родитель

и так далее для каждой группы в первой колонке, всег вышестоящие группы во второй

и использовать это для этой задачи

Где можно будет указать .... СОединение Номенклатура.Родитель = ТЗ.Родитель и далее обрабатывается

условие с Вышестоящими родителями

итак процедуры

/// это основная процедура где и нужно произвести соединение по иерархии

Процедура КнопкаВыполнитьНажатие(Кнопка)

 
М = Новый МенеджерВременныхТаблиц;

 
Запрос = Новый Запрос;
 
Запрос.УстановитьПараметр("Номенклатура",Номенклатура);

 
ПолучитьНаборРодителей(М);
 
Запрос.МенеджерВременныхТаблиц = М;

 
// это конечно можно сразу в условии ГДЕ в ИЕРАРХИИ решить
 // это просто пример
 
Запрос.Текст =

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

 
РЕзультат = Запрос.Выполнить().Выгрузить();
 
ЭлементыФормы.ТЗ_1.Значение = Результат.Скопировать();

КонецПроцедуры


// Эти две процедуры создают ТЗ с группами

// первая процедура выбирает все группы

// вторая заполняет ТЗ вышестоящими родителями для родителя первой колонки

Процедура ПолучитьНаборРодителей(МенВремТаблиц)


 
НовТЗСоВсемиРодителями = Новый ТаблицаЗначений;
 
ТипНоменклатура = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
 
НовТЗСоВсемиРодителями.Колонки.Добавить("ПервыйРодитель",ТипНоменклатура);
 
НовТЗСоВсемиРодителями.Колонки.Добавить("РодительГдеТоНадНоменклатурой",ТипНоменклатура);

 
Запрос = Новый Запрос;
// Запрос.УстановитьПараметр("Номенклатура",Номенклатура);
 
Запрос.Текст =
 
"ВЫБРАТЬ
 | Номенклатура.Ссылка КАК ПервыйРодитель
 |ИЗ
 | Справочник.Номенклатура КАК Номенклатура
 |ГДЕ
 | Номенклатура.ЭтоГруппа
// | И Номенклатура.Ссылка = &Номенклатура
 
|
 |СГРУППИРОВАТЬ ПО
 | Номенклатура.Ссылка"
 
;
 
Результат = Запрос.Выполнить().Выгрузить();
 Для каждого
стр Из Результат Цикл
  Если
стр.ПервыйРодитель.Родитель.Пустая() Тогда
  
стрТЗ = НовТЗСоВсемиРодителями.Добавить();
  
стрТЗ.ПервыйРодитель     = стр.ПервыйРодитель;
  
стрТЗ.РодительГдеТоНадНоменклатурой = Справочники.Номенклатура.ПустаяСсылка();
  Иначе
  
ПолучитьВсехРодителей(НовТЗСоВсемиРодителями,стр.ПервыйРодитель,стр.ПервыйРодитель.Родитель);
  КонецЕсли;
 КонецЦикла;

 
НовТЗСоВсемиРодителями.Сортировать("ПервыйРодитель");

 
////////////////////////////////////////////////////////////////////////
 ///// для наглядоности, выгружаем в Таблицу значений на форме //////////
 ////////////////////////////////////////////////////////////////////////
 
ЭлементыФормы.ТЗ_.Значение = НовТЗСоВсемиРодителями.Скопировать();
 
ЭлементыФормы.ТЗ_.ОбновитьСтроки();

 
Запрос = Новый Запрос;
 
Запрос.МенеджерВременныхТаблиц = МенВремТаблиц;
 
Запрос.УстановитьПараметр("ВоВремТабл",НовТЗСоВсемиРодителями);
 
Запрос.Текст =
 
"ВЫБРАТЬ
 | ВоВремТабл.ПервыйРодитель,
 | ВоВремТабл.РодительГдеТоНадНоменклатурой
 |ПОМЕСТИТЬ ВремТаб
 |ИЗ
 | &ВоВремТабл КАК ВоВремТабл"
 
;
 
Запрос.Выполнить();

КонецПроцедуры

Процедура
ПолучитьВсехРодителей(ТЗ,Родитель,РодительНадРодителем)

 Если
РодительНадРодителем.Пустая() Тогда
  Возврат;
 КонецЕсли;

 
стрТЗ = ТЗ.Добавить();
 
стрТЗ.ПервыйРодитель     = Родитель;
 
стрТЗ.РодительГдеТоНадНоменклатурой = РодительНадРодителем;

 
ПолучитьВсехРодителей(ТЗ,Родитель,РодительНадРодителем.Родитель);

КонецПроцедуры

Файлы обработки:

-