2014-09-05 3 views
2

У меня есть таблица с HierarchyID и вы хотите выбрать родительскую и дочернюю базы для дочернего атрибута.Выберите родителя и ребенка на SQL Server с идентификатором HierarchyID

Вот таблица:

CREATE TABLE #BOMTbl 
(
    ItemNo HIERARCHYID NOT NULL, 
    Lvl AS ItemNo.GetLevel() PERSISTED, 
    MatID VARCHAR(25) NULL, 
    CONSTRAINT PK_#BOMTbl PRIMARY KEY NONCLUSTERED(ItemNo) 
); 

insert into #BOMTbl (ItemNo,MatID) values 
('/1/',''), 
('/1/1/',''), 
('/1/1/1/','MA-A'), 
('/1/1/2/','MA-A'), 
('/1/1/3/','MA-B'), 
('/1/2/',''), 
('/1/2/1/','MA-B'), 
('/1/2/2/','MA-B'), 
('/1/3/',''), 
('/1/3/1/','PW-A'), 
('/1/3/2/','PW-A'), 
('/1/4/',''), 
('/1/4/1/','PW-B'), 
('/1/4/2/','PW-B'), 
('/1/5/','0001'), 
('/1/6/','0001'), 
('/1/7/','0002'), 
('/1/8/','0003') 

Я хочу, чтобы выбрать таблицу с результатом, как это:

ItemNo ItemID Lvl MatID 
0x5AC0 /1/1/ 2 
0x5AD6 /1/1/1/ 3 MA-A 
0x5ADA /1/1/2/ 3 MA-A 
0x5B40 /1/2/ 2 
0x5ADE /1/1/3/ 3 MA-B 
0x5B56 /1/2/1/ 3 MA-B 
0x5B5A /1/2/2/ 3 MA-B 
+0

Это результат приходит от всех детей с MatId как 'MA%'? –

ответ

0
select ItemNo, ItemNo.ToString() AS ItemID, Lvl, MatID from BOMTbl p 
WHERE exists 
(select * from BOMTbl c 
where c.MatID like 'MA%' 
and (c.ItemNo.GetAncestor(1) = p.ItemNo 
     or c.ItemNo.GetAncestor(0) = p.ItemNo)) 

SQLFiddle

+0

Привет, Чанг, Спасибо за код. Это простой :). Можете ли вы предложить мне книгу или статью о запросе HierarchyID. – user3335691

+0

@ user3335691 Поиск "Иерархия" в SO. Проверьте эти случаи с помощью sqlfiddle. –

0

Будет ли следующий запрос помощи?

select ItemNo, ItemNo.ToString() AS ItemID, Lvl, MatID from #BOMTbl 
WHERE ItemNo.IsDescendantOf('/1/1/') = 1 
UNION 
select ItemNo, ItemNo.ToString() AS ItemID, Lvl, MatID from #BOMTbl 
WHERE ItemNo.IsDescendantOf('/1/2/') = 1 
+0

@ zhoingxiao37: Спасибо за ваш ответ. Я следую вашему коду для объединения двух запросов, и результат правильный :). : выберите ITEMNO, itemno.ToString(), как ItemID, Lvl, MatID из #BOMTbl где MatID LIKE 'MA%' объединение Выберите ITEMNO, ItemNo.ToString(), как ItemID, Lvl, MatID из #BOMTbl где ITEMNO в ( Select ITEMNO .GetAncestor (ITEMNO .GetLevel() -. (выбрать макс (ур-1) от #BOMTbl где 'MA%' MatID LIKE)) ToString() из #BOMTbl где MatID LIKE ' MA% ' ) – user3335691

0

я придумал:

with cte as (
    select * 
    from #BOMTbl 
    where MatId like 'MA%' 
) 
select * 
from cte as child 
union 
select parent.* 
from cte as child 
join #BOMTbl as parent 
    on child.ItemNo.GetAncestor(1) = parent.ItemNo 
+0

Я думаю, что использование левого соединения вместо объединения должно быть более эффективным. –

+0

Каким образом? В частности, какой * конкретный * запрос с использованием левого соединения вы бы предположили, что будет «более эффективным», чем то, что у меня здесь? Я не защищаюсь, но вы не можете сказать, что левые соединения всегда более эффективны, чем союз. Все, что вы можете сделать, это сказать, что конкретный запрос будет более эффективным, чем другой конкретный запрос, учитывая обстоятельства данных (структура, качество и количество). –

+1

Извините! Только в этом случае я имею в виду «select different parent.» от BOMTbl как родительский left join cte как дочерний на child.ItemNo.GetAncestor (1) = parent.ItemNo или child.ItemNo.GetAncestor (0) = parent .ItemNo , где child.itemno не является нулевым, достигнет того же результата, уменьшив одно сканирование таблицы. –

Смежные вопросы