2015-08-09 58 views
0

我正在使用以下CTE來獲取經理和員工的層次結構,我有一個員工的多個經理,在這種情況下,我不希望CTE重複爲該員工一次又一次因爲它是做在我的代碼 - getemp()是一個簡單的函數返回employeeid, name and managerID如何避免遞歸CTE重複定位值

;With hierarchy as 
(
select [Level]=1 , * from dbo.getemp() where managerid = 1 
union all 
select [Level]+1 , e.* from getemp() e 
join hierarchy h on h.employeeid = e.managerid 

) 
Select * from hierarchy 

編輯後 - 以下辦法爲我工作。 CTE有可能嗎?

SET NOCOUNT ON; 
    DECLARE @Rows int 


    SELECT [Level] = ISNULL(1,0), 
     employeeid = ISNULL(employeeid, 0), 
     empname = CAST(empname as varchar(10)), 
     managerid = ISNULL(managerid,0) 
     into #Temp1 
     from dbo.getemp() as a1 
     where a1.managerid = @Top1 
     --select * from #Temp1 
     SELECT @[email protected]@ROWCOUNT 

     DECLARE @I INT = 2; 
     while @Rows > 0 
     BEGIN 

    Insert into #Temp1 
    select @I as Level, b.employeeid, b.empname, b.managerid from #Temp1 as e 
    inner join (select [employeeid], [empname], [managerid] from dbo.GetEmp())  as b on b.managerid = e.employeeid 
    where e.Level = @I - 1 
    and not exists (
    SELECT 1 FROM #Temp1 t 
    WHERE b.employeeid = t.employeeid 
    AND b.managerid = t.managerid); 
    SELECT @[email protected]@ROWCOUNT 
    --SELECT @Rows AS Rows 
    IF @Rows > 0 
    BEGIN 
    SELECT @I = @I + 1; 
    END 


END 

select distinct * from #Temp1 
END 
+0

如果員工有幾個管理人員,其中之一應在經理ID被退回? –

+0

@JamesZ如果員工有兩個經理,那麼它應該返回兩個managerID的行。但是對於下一次遞歸,它應該只考慮員工一次而不是兩次。 – vishakha

+0

示例數據和預期結果將會有所幫助。 CTE的一個問題是,遞歸查詢無法訪問除最近添加的行之外的其他任何內容。如果你需要訪問先前處理過的行的所有_all_,那麼你可能需要使用'WHILE'循環並將結果組裝到一個臨時表中,直到「@@ ROWCOUNT = 0」。 – HABO

回答

0

無法找到使用CTE的解決方案,所以我用了while循環,以避免重複錨,這裏的代碼..

DECLARE @Rows int 
    SELECT [Level] = ISNULL(1,0), 
     employeeid = ISNULL(employeeid, 0), 
     empname = CAST(empname as varchar(10)), 
     managerid = ISNULL(managerid,0) 
     into #Temp1 
     from dbo.getemp() as a1 
     where a1.managerid = @Top1 
     --select * from #Temp1 
     SELECT @[email protected]@ROWCOUNT 

     DECLARE @I INT = 2; 
     while @Rows > 0 
     BEGIN 

    Insert into #Temp1 
    select @I as Level, b.employeeid, b.empname, b.managerid from #Temp1 as e 
    inner join (select [employeeid], [empname], [managerid] from dbo.GetEmp())  as b on b.managerid = e.employeeid 
    where e.Level = @I - 1 
    and not exists (
    SELECT 1 FROM #Temp1 t 
    WHERE b.employeeid = t.employeeid 
    AND b.managerid = t.managerid); 
    SELECT @[email protected]@ROWCOUNT 
    --SELECT @Rows AS Rows 
    IF @Rows > 0 
    BEGIN 
    SELECT @I = @I + 1; 
    END 
END 
select distinct * from #Temp1 
END 
0

既然你有幾個管理人員,這意味着人們也可以在幾個不同的層次,由於在經理有不同的等級,你可以只需要爲每個分支的最低水平像這樣的東西:

;With hierarchy as 
(
    select [Level]=1 , * from dbo.getemp() where managerid = 1 
    union all 
    select [Level]+1 , e.* from getemp() e 
    join hierarchy h on h.employeeid = e.managerid 
) 

Select min(Level) as Level, employeeid, name, managerid from hierarchy 
group by employeeid, name, managerid 

使用函數在每次遞歸中返回所有員工可能不是關於性能的最佳解決方案,尤其是如果它不是內聯函數。您可能想考慮使用例如臨時。表,如果你不能直接讀取表。

+0

感謝您的答案,我們有系統中現有的功能,我需要使用...爲了問這個問題,我給了emp經理場景..與您的答案仍然CTE將一次又一次地爲同一員工遞減..這是我想要避免..我不需要'級別'的任何特定原因,如果刪除,有助於獲得正確的查詢 – vishakha

+0

@vishakha如果您將數據加載到臨時數據中。表,你還在使用這個功能嗎?爲什麼你試圖避免同一個人被多次提取? –

+0

@ JamesZ我的壞..我不明白你在說什麼..會嘗試使用臨時表 – vishakha