我的猜測是ParentItem沒有索引。 並且在該字段中有3個連接,全表掃描使其變慢。
但ID可能是主鍵,所以這是索引。
如果ParentItem添加索引是不是一種選擇?
然後,你可以通過一個臨時表與父母的索引。
CREATE TABLE #tmpItem (ParentID int, ID int);
INSERT INTO #tmpItem (ParentID, ID)
SELECT ParentItem, ID
FROM dbo.Item;
CREATE CLUSTERED INDEX #IDX_C_tmpItem ON #tmpItem(ParentID);
SELECT --TOP (100) PERCENT
Item_0.ID AS ID,
Item_0.ItemLookupCode AS ItemLookupCode,
Item_0.UnitOfMeasure AS UnitOfMeasure,
Item_1.ID AS ChildID1,
Item_1.ItemLookupCode AS ChildItemLookupCode1,
Item_1.ParentItem AS ChildParentItem1,
Item_1.UnitOfMeasure AS ChildUOM1,
Item_2.ID AS ChildID2,
Item_2.ItemLookupCode AS ChildItemLookupCode2,
Item_2.ParentItem AS ChildParentItem2,
Item_2.UnitOfMeasure AS ChildUOM2,
Item_3.ID AS ChildID3,
Item_3.ItemLookupCode AS ChildItemLookupCode3,
Item_3.ParentItem AS ChildParentItem3,
Item_3.UnitOfMeasure AS ChildUOM3
FROM (
SELECT I0.ID as ID0, I1.ID as ID1, I2.ID as ID2, I3.ID as ID3
FROM #tmpItem AS I0
LEFT JOIN #tmpItem AS I1 ON (I0.ID = I1.ParentID)
LEFT JOIN #tmpItem AS I2 ON (I1.ID = I2.ParentID)
LEFT JOIN #tmpItem AS I3 ON (I2.ID = I3.ParentID)
) Q
LEFT JOIN dbo.Item Item_0 ON Q.ID0 = Item_0.ID
LEFT JOIN dbo.Item Item_1 ON Q.ID1 = Item_1.ID
LEFT JOIN dbo.Item Item_2 ON Q.ID2 = Item_2.ID
LEFT JOIN dbo.Item Item_3 ON Q.ID3 = Item_3.ID;
下面只是一個使用遞歸查詢的實驗。
使用ID上的索引。
是的,我知道,它沒有返回沒有孩子的父母。請不要判斷。
declare @Item table (ID int primary key, ItemLookupCode varchar(11), UnitOfMeasure varchar(3), ParentItem int);
insert into @Item (ID, ItemLookupCode, UnitOfMeasure, ParentItem) values
(111,'100006C0005','CRT',0), (112,'100006B0001','BAG',111),
(221,'100027C0002','CRT',0), (222,'100027T0012','PCT',221), (223,'100027P0001','PC',222),
(224,'100027X0001','XX',223),(225,'100027Y0001','YY',223),
(226,'100027Z0001','ZZ',225);
WITH RCTE AS
(
select ID as StartID, 0 as PrevID, 0 as Level, ID, ParentItem as ParentID, ItemLookupCode, UnitOfMeasure
from @Item
union all
select RCTE.StartID, RCTE.ID, RCTE.Level + 1, t.ID, t.ParentItem, t.ItemLookupCode, t.UnitOfMeasure
from RCTE
join @Item t on (RCTE.ParentID = t.ID)
)
select
max(case when ReverseLeveL = 0 then ID end) as ID0,
max(case when ReverseLeveL = 0 then ItemLookupCode end) as ItemLookupCode0,
max(case when ReverseLeveL = 0 then UnitOfMeasure end) as UnitOfMeasure0,
max(case when ReverseLeveL = 1 then ID end) as ID1,
max(case when ReverseLeveL = 1 then ItemLookupCode end) as ItemLookupCode1,
max(case when ReverseLeveL = 1 then UnitOfMeasure end) as UnitOfMeasure1,
max(case when ReverseLeveL = 2 then ID end) as ID2,
max(case when ReverseLeveL = 2 then ItemLookupCode end) as ItemLookupCode2,
max(case when ReverseLeveL = 2 then UnitOfMeasure end) as UnitOfMeasure2,
max(case when ReverseLeveL = 3 then ID end) as ID3,
max(case when ReverseLeveL = 3 then ItemLookupCode end) as ItemLookupCode3,
max(case when ReverseLeveL = 3 then UnitOfMeasure end) as UnitOfMeasure3
from (
SELECT *, row_number() over (partition by StartID order by Level desc)-1 as ReverseLeveL
from RCTE
where Level <= 3
) Q
group by StartID
having max(case when ReverseLeveL = 1 then ID end) is not null;
使用遞歸查詢(CTE)。請參閱https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx –