Например так. Делаем дополнительную таблицу, в которой хранятся пары ID, ParentID для всех вышестоящих родителей. У меня это выглядит так:
// Вспомогательная таблица для хранения иерархии объектов приложения прав
ЗапросНаСозданиеТаблицы = "
|Set NoCount ON
|CREATE TABLE Дерево_ТипыОбъектовПриложенияРазрешений (
| ID char(9) NOT NULL,
| ParentID char(9) NOT NULL
|)";
ЗапросНаСозданиеИндексов = "
|Set NoCount ON
|CREATE INDEX [IX_Дерево_ТипыОбъектовПриложенияРазрешений_ID]
| ON dbo.[Дерево_ТипыОбъектовПриложенияРазрешений](ID)
|CREATE INDEX [IX_Дерево_ТипыОбъектовПриложенияРазрешений_ParentID]
| ON dbo.[Дерево_ТипыОбъектовПриложенияРазрешений](ParentID)
|";
Делаем триггеры
ИмяТриггера = "ТриггерВставка_Иерархия_ТипыОбъектовПриложенияРазрешений";
ИмяТаблицы = МД.ИмяТаблицыСправочника("ТипыОбъектовПриложенияРазрешений");
//insert
ТекстЗапроса = "CREATE TRIGGER "+ИмяТриггера+" ON "+ИмяТаблицы+"
|AFTER INSERT
|AS
|DECLARE @ID char(9), @ParentID char(9), @Level tinyint
|SELECT @ID = ID, @ParentID = ParentID FROM Inserted
|SET @Level = 0
|WHILE @ParentID <> '"+глПустойИдентификатор9+"'
|BEGIN
| INSERT INTO "+ИмяВторойБазы+"Дерево_ТипыОбъектовПриложенияРазрешений
| (ID, ParentID) VALUES (@ID, @ParentID)
| SELECT @ParentID = ParentID FROM "+ИмяТаблицы+" WHERE ID = @ParentID
| SET @Level = @Level + 1
|END
|
|UPDATE "+ИмяТаблицы+" SET "+ПолеПорядокСортировки+" = @Level WHERE ID = @ID
|";
Если СоздатьТриггер(ИмяТриггера, ТекстЗапроса, 1) = 0 Тогда
Возврат 0;
КонецЕсли;
//update
ИмяТриггера = "ТриггерОбновление_Иерархия_ТипыОбъектовПриложенияРазрешений";
ТекстЗапроса = "CREATE TRIGGER "+ИмяТриггера+" ON "+ИмяТаблицы+"
|AFTER UPDATE
|AS
|DECLARE @ID char(9), @ParentID char(9), @Level tinyint
|SELECT @ID = ID, @ParentID = ParentID FROM Inserted
|DELETE FROM "+ИмяВторойБазы+"Дерево_ТипыОбъектовПриложенияРазрешений WHERE ID = @ID
|SET @Level = 0
|WHILE @ParentID <> '"+глПустойИдентификатор9+"'
|BEGIN
| INSERT INTO "+ИмяВторойБазы+"Дерево_ТипыОбъектовПриложенияРазрешений (ID, ParentID) VALUES (@ID, @ParentID)
| SELECT @ParentID = ParentID FROM "+ИмяТаблицы+" WHERE ID = @ParentID
| SET @Level = @Level + 1
|END
|
|UPDATE "+ИмяТаблицы+" SET "+ПолеПорядокСортировки+" = @Level WHERE ID = @ID
|";
Если СоздатьТриггер(ИмяТриггера, ТекстЗапроса, 1) = 0 Тогда
Возврат 0;
КонецЕсли;
//delete
ИмяТриггера = "ТриггерУдаление_Иерархия_ТипыОбъектовПриложенияРазрешений";
ТекстЗапроса = "CREATE TRIGGER "+ИмяТриггера+" ON "+ИмяТаблицы+"
|AFTER DELETE
|AS
|DECLARE @ID char(9)
|SELECT @ID = ID FROM Deleted
|DELETE FROM "+ИмяВторойБазы+"Дерево_ТипыОбъектовПриложенияРазрешений WHERE ID = @ID
|";
Если СоздатьТриггер(ИмяТриггера, ТекстЗапроса, 1) = 0 Тогда
Возврат 0;
КонецЕсли;
И теперь получить все подчинённые элементы - дело техники. Например так:
Запрос.Подготовить("SET NoCount ON
|SELECT
| ТипыОбъектов.ID Элемент
|FROM
| "+ИмяВторойБазы+"Дерево_ТипыОбъектовПриложенияРазрешений Дерево (NoLock)
| INNER JOIN $Справочник.ТипыОбъектовПриложенияРазрешений ТипыОбъектов (NoLock) ON ТипыОбъектов.ID = Дерево.ID
|WHERE
| Дерево.ParentID = :Группа