2017-07-02 231 views
0

實施例的表結構:SQL:優化遞歸CTE

EmployeeId TeamleaderId TopTeamleaderId LEVEL ParentTree CompanyId 
1   0    0     0  NULL   1 
2   1    1     1  2>1   1 
3   2    1     2  3>2>1   1 

TeamleaderIdforeignKey參照EmployeeId在同一表

目標: 每當行被插入在表中與EmployeeIdTeamleaderId,CompanyId自動填充TopTeamleaderId,LEVELParentTreeAFTER INSERT觸發

代碼:

WITH CTE AS (
    SELECT EmployeeId, TeamleaderId,0 AS [Level], CAST(EmployeeId AS varchar(100)) AS Heirarchy, TopTeamleaderId 
    FROM dbo.Employee 
    WHERE EmployeeId IN (SELECT EmployeeId FROM Employee WHERE TeamleaderId IS NULL 
    AND CompanyId IN(SELECT DISTINCT CompanyId FROM INSERTED)) 

    UNION ALL 

    SELECT mgr.EmployeeId, mgr.TeamleaderId, CTE.[Level] +1 AS [Level], 
     CAST((CAST(mgr.EmployeeId AS VARCHAR(100)) + '>' + CTE.Heirarchy) AS varchar(100)) AS Heirarchy, CTE.TopTeamleaderId 
    FROM CTE 
    INNER JOIN dbo.Employee AS mgr 
     ON TaskCTE.EmployeeId = mgr.ParentTeamleaderId 
) 
UPDATE Employee SET [LEVEL] = TC.[LEVEL], ParentTree = TC.Heirarchy, TopTeamleaderId = TC.TopTeamleaderId 
FROM dbo.Employee AS Employee 
JOIN (SELECT * FROM CTE WHERE EmployeeId IN(SELECT DISTINCT EmployeeId FROM INSERTED) AND ParentTeamleaderId IS NOT NULL) TC 
ON 
Employee.EmployeeId = TC.EmployeeId 

問題: 想象有像百萬員工在一個公司,這個查詢需要很長的時間來執行。如何優化它,以便只有插入行的父母纔會被記錄下來?

+1

什麼是你的樓內設有商務規則來做到這一點?請解釋並舉個例子。 –

+0

看到規則不明確,也沒有你的餐桌設計的目的。下腳本是好的,但在你的腳本之上,即使從遞歸CTE的角度來看也是錯誤的。它也可以被優化。 – KumarHarsh

回答

2

遞歸CTE是偉大的,但正如你可以看到,性能可能會受到更大的層次結構的影響。我堅信臨時表沒有恥辱。

以下將在0.784秒內生成200K點層次結構。

Select EmployeeId 
     ,TeamleaderId 
     ,Lvl=1 
     ,TopTeamleaderId = 0 
     ,ParentTree=cast(EmployeeId as varchar(500)) 
     ,CompanyID 
Into #TempBld 
From Employee 
Where TeamleaderId is null 

Declare @Cnt int=1 
While @Cnt<=30  --<< Set Your Max Level 
    Begin 
     Insert Into #TempBld 
     Select A.EmployeeId 
       ,A.TeamleaderId 
       ,B.Lvl+1 
       ,IIF(B.Lvl=1,B.EmployeeId,B.TopTeamleaderId) 
       ,concat(A.EmployeeId,'>',B.ParentTree) 
       ,A.CompanyID 
     From Employee A 
     Join #TempBld B on ([email protected] and A.TeamleaderId=B.EmployeeId) 
     Set @[email protected]+1 
    End 

--Select * from #TempBld Order by ParentTree 

返回

enter image description here

+0

然而,我仍然在回答這個問題,乍一看,生成的「ParentTree」與我想要的相反。例如,在您的示例中,對於'EmployeeId = 16','ParentTree'應該是'16> 1' –

+0

@ShyamalParikh更正了ParentTree的序列 –