2017-07-02 191 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的序列 –