powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Деревянные списки
8 сообщений из 8, страница 1 из 1
Деревянные списки
    #32028263
Вячеслав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте! Возможно проблема была ранее обсуждена на форуме, - тогда
спасибо за ссылку, но в любом случае не могу решить следущую задачу:

Имеем таблицу, описывающюю дерево подразделений предприятия :
ID, PARENT_ID, LEV - собственно id, ссылка на родитель-подразделение на уровень выше,
уровень вложенности подразделения в дереве. Необходимо по заданному id выдать набор этих самых id всех входящих в заданное подразделение подразделений.

Поля: ID,PARENT_ID,LEV
1 NULL 1 - Предприятие
2 1 2 - Цех 1
3 1 2 - Цех 2
4 2 3 - Отдел Цеха 1
5 3 3 - Отдел Цеха 2
6 5 4 - Подотдел Отдела Цеха 2

т.о. задав id = 1 должны получить список id 1,2,3,4,5
задав id = 3 -> 3,5,6

Заранее благодарен.
...
Рейтинг: 0 / 0
Деревянные списки
    #32028268
Almi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я для работы с деревом использую три поля:
id, parent_id и way, где way строка и в ней хранится вся ветка вложенности (по id через разделитель) до текущей позиции, например '0|1|5|130|135'.
Если нужно вытащить всю вложенность начиная с текущей позиции (например с 5) то:
select id from table where way like '0|1|5'+'%'
...
Рейтинг: 0 / 0
Деревянные списки
    #32028269
Almi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я для работы с деревом использую три поля:
id, parent_id и way, где way строка и в ней хранится вся ветка вложенности (по id через разделитель) до текущей позиции, например '0|1|5|130|135'.
Если нужно вытащить всю вложенность начиная с текущей позиции (например с 5) то:
select id from table where way like '0|1|5'+'%'
...
Рейтинг: 0 / 0
Деревянные списки
    #32028284
Варяг
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если проектирование начинается с нуля, полезно разобраться со статьей Иерархические структуры, не требующие сопровождения
...
Рейтинг: 0 / 0
Деревянные списки
    #32028326
Серж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно написать хранимку, которая будет выбирать все поддерово, обрабатывая его по слоям.
Делать это придлется через врем. таблицы.

Вот пример

CREATE PROCEDURE sp_get_child_department
@department_id int,
@table_name varchar(12
--Вычислить список подразделений дочерних по отношению к подразделению с кодом @department_id.
--Список сохраняется в предварительно созданной таблице с именем @table_name формата (dep_id INT).
AS
begin
declare
@rc int,
@SQLText NVARCHAR(1000)

create table #final ([id] int)
create table #tmp1 ([id] int)
create table #tmp2 ([id] int)

insert into #tmp1 ([id]) values(@department_id)
insert into #final ([id]) values(@department_id)
set @rc = 1
while @rc != 0
begin
truncate table #tmp2
insert into #tmp2 ([id]) select department.department_id from department join #tmp1 on department.department_pred_id = #tmp1.[id]
select @rc = @@rowcount
if @rc != 0
begin
insert into #final ([id]) select #tmp2.[id] from #tmp2
truncate table #tmp1
insert into #tmp1 ([id]) select department.[department_id] from department join #tmp2 on department.department_pred_id = #tmp2.[id]
select @rc = @@rowcount
if @rc != 0 insert into #final ([id]) select #tmp1.[id] from #tmp1
end
end

declare @sqltext nvarchar(1000)
SET @sqltext = 'INSERT INTO '+@table_name+'(dep_id) (SELECT #final.id FROM department JOIN #final ON department.department_id = #final.[id])'
EXEC sp_executesql @sqltext
end
...
Рейтинг: 0 / 0
Деревянные списки
    #32028327
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то, способов хранения древовидной структуры достаточно много.
Еще один пример способа хранения можно посмотреть здесь: http://www.sdm.viptop.ru/articles/sqltrees.html

А по поводу собственно вопроса:

DECLARE @IDRoot Int, @AllChild VarChar(100)
SET @IDRoot = 1 -- значение ID корня, для которого ищем всех потомков
SET @AllChild=CONVERT(VarChar(10),@IDRoot) -- найденный список всех потомков

SELECT ID, LEV INTO #tabTmp FROM TabTree WHERE Parent_ID=@IDRoot

WHILE (SELECT count(*) FROM #TabTmp)>0
BEGIN
SELECT TOP 1 @IDRoot=ID FROM #tabTmp ORDER BY LEV -- выделяю первую запись из таблицы #TabTmp
DELETE FROM #tabTmp WHERE ID=@IDRoot -- Удаляю уже не нужную первую запись
-- Добавляю в таблицу #TabTmp всех потомков для только что удаленной записи
INSERT INTO #tabTmp (ID,LEV) SELECT ID,LEV FROM TabTree WHERE Parent_ID=@IDRoot
SET @AllChild=@AllChild+','+CONVERT(VarChar(10),@IDRoot) -- Пополняю выходное значение
END

select @AllChild

Список будет упорядочен по возрастанию уровня вложенности (LEV)
...
Рейтинг: 0 / 0
Деревянные списки
    #32028329
Garry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Предлагаю создать еще одну таблицу
Таблица должна содержать два поля ID и ID_parent
Для каждого "родительского" подразделения в этой таблице должно быть столько записей, сколько "детей" у него всего есть.

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

id id_parent
1 1
2 2
3 3
4 4
5 5
6 6
2 1
3 1
4 1
5 1
6 1
4 2
5 3
6 3
6 5

запросы
select id from tree where id_parent = 1
select id from tree where id_parent = 3

возвращают искомую последовательность

Плюсы такого подхода
- можно без проблем искать как "вверх по дереву" так и "вниз по дереву" с любого уровня.
- Хорошее быстродействие.
Заполнение таблицы tree происходит при заполнении таблицы подразделений (в этом случае алгоритм наиболее простой).
Хотя, конечно, неплохо иметь под рукой процедуру, которая выполняет полный обход дерева и перестраивает данные в таблице tree...
...
Рейтинг: 0 / 0
Деревянные списки
    #32028331
Garry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да совсем забыл подчеркнуть самый главный плюс
- поиск по дереву с любого уровня (!)
вверх или вниз происходит за один зарпос, что значительно быстрее поуровневой обработки.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Деревянные списки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]