Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Рекурсивный обход оператором WITH REC  [new]
ariecberkut
Member

Откуда: Славянск
Сообщений: 8
Прошу помощи
Мне нужно получить рекурсивный обход дерева родитель/ потомок в следующем формате.
Исходные данные - таблица PC (столбцы proj_aid - код родителя, part_aid - код потомка)
Выходные данные - таблица (столбцы proj_aid - код родителя, part_aid - код потомка,pos_id - код потомка головной записи)

DECLARE @art_id = 4271 -- Код головного изделия
WITH Rec(PROJ_AID,PART_AID,pos_id)
AS (
SELECT PROJ_AID,PART_AID FROM PC where PROJ_AID= @art_id
UNION ALL
SELECT PC.PROJ_AID,PC.PART_AID FROM Rec inner join PC on Rec.PART_AID = PC.PROJ_AID
)


Вопрос как доработать данный рекурсивный запрос, чтобы добавить в результат pos_id
4 сен 17, 09:50    [20768958]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
aleks222
Guest
DECLARE @art_id = 4271 -- Код головного изделия
WITH Rec(PROJ_AID,PART_AID,pos_id)
 AS (
 SELECT PROJ_AID,PART_AID, pos_id = PROJ_AID FROM PC where PROJ_AID= @art_id 
 UNION ALL
 SELECT PC.PROJ_AID,PC.PART_AID, Rec.pos_id  FROM Rec inner join PC on Rec.PART_AID = PC.PROJ_AID 
 ) 
4 сен 17, 10:15    [20769030]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
ariecberkut
Member

Откуда: Славянск
Сообщений: 8
Спасибо , помогли.
Только до конца правилльн запрос выглядит вот так.
DECLARE @art_id = 4271 -- Код головного изделия
WITH Rec(PROJ_AID,PART_AID,pos_id)
AS (
SELECT PROJ_AID,PART_AID, pos_id = PROJ_AID FROM PC where PART_AID= @art_id -- Здесь вместо PROJ_AID поставил PART_AID
UNION ALL
SELECT PC.PROJ_AID,PC.PART_AID, Rec.pos_id FROM Rec inner join PC on Rec.PART_AID = PC.PROJ_AID
)
4 сен 17, 10:46    [20769115]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
iap
Member

Откуда: Москва
Сообщений: 46953
ariecberkut,

только WITH Rec - это не оператор
4 сен 17, 11:23    [20769215]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
ariecberkut
Member

Откуда: Славянск
Сообщений: 8
Возможно.Мой когнитивный аппарат в области MSSQL за последние годы достаточно ослаб
4 сен 17, 13:34    [20769692]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
ariecberkut
Member

Откуда: Славянск
Сообщений: 8
/ Исходные данные - код головного родителя (целое число)

DECLARE @main_id INT SET @main_id = <код головного родителя>

// Есть временнаая таблица для результата @tab и постоянная таблица PC для извлечения данных
// art_id - код потомка
// parent_id - код родителя
// count_pc - количество потомка в составе родителя
// gencount - количество потомка в составе головного родителя
DECLARE @tab table (art_id INT ,parent_id INT ,count_pc FLOAT,gencount FLOAT)
WITH REC (art_id,parent_id,count_pc,gencount)
AS
(
SELECT art_id,parent_id ,count_pc, count_pc as gencount FROM pc WHERE parent_id = @main_id
UNION ALL
SELECT art_id,parent_id,count_pc,(Rec.count_pc * pc.count_pc) as gencount FROM rec INNER JOIN pc ON REC.art_id = pc.parent_id
)
INSERT INTO @tab (art_id,parent_id,count_pc,gen_count) SELECT art_id,parent_id,count_pc,gen_count FROM REC

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

Есть пожелание путём доработки кода получить в рамках этой методики строку полного пути входимости элемента в головной узел в виде строки с разделителем.
Например :
232232|4271|6988|12344
232232|4271|6988|12345
232233|4271|6988|12344
232234|4271|6988|12345

Попытка решить вопрос тем же методом что и вычисление общего количества, только путём строчкого суммирования id элементов,преобразованный в строку успехом не увенчалась. SQL не позволяет такого в рамках данной методики.
Прошу знатоков помочь в решении данного вопроса
1 окт 17, 14:30    [20834517]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
aleks222
Guest
DECLARE @main_id INT SET @main_id = <код головного родителя>

// Есть временнаая таблица для результата @tab и постоянная таблица PC для извлечения данных
// art_id - код потомка
// parent_id - код родителя
// count_pc - количество потомка в составе родителя
// gencount - количество потомка в составе головного родителя
DECLARE @tab table (art_id INT ,parent_id INT ,count_pc FLOAT,gencount FLOAT, path varchar(max) )
WITH REC (art_id,parent_id,count_pc,gencount)
AS 
(
SELECT art_id,parent_id ,count_pc, count_pc as gencount, path = cast(art_id as nvarchar(max)) FROM pc WHERE parent_id = @main_id
UNION ALL
SELECT art_id,parent_id,count_pc,(Rec.count_pc * pc.count_pc) as gencount, path = rec.path + N'|' + cast(pc.art_id as nvarchar(max)) FROM rec INNER JOIN pc ON REC.art_id = pc.parent_id 
)
INSERT INTO @tab (art_id,parent_id,count_pc,gen_count, path) SELECT art_id,parent_id,count_pc,gen_count, path FROM REC
1 окт 17, 17:55    [20834715]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный обход оператором WITH REC  [new]
ariecberkut
Member

Откуда: Славянск
Сообщений: 8
Благодарю. Я такой вариант уже пробовал, только кастил в VARCHAR.
Не получилось.Попробую ваш и отпишусь
1 окт 17, 18:02    [20834720]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить