2014-06-23 168 views
1

我與員工的記錄表,顯示僱員的關係,他們舉報誰:CTE遞歸查詢

From_ID position   TO_ID position 
---------------------------------------- 
1   Lowest_employee 3  employee 
3   employee   4  employee 
4   employee   5  BOSS 
2   Lowest_employee 6  employee 
6   employee   3  employee 
10  Lowest_employee 50  BOSS2 

我想顯示的結果是這樣的,與員工/老闆的ID :

EmployeeID BossID 
-------------------- 
1   5 
2   5 
10   50 

enter image description here

這意味着員工1和ID 5 2報告和僱員10個報告到另一個老闆ID 50.

我知道我需要使用CTE和遞歸查詢,但無法理解如何完成,我更新CTE遞歸查詢。

我讀這篇文章,但它沒有任何意義,我MS link

與實現,這將是有用的需要查詢任何幫助。

+0

我很努力地理解你在問什麼,重新閱讀你的問題(忘記你所知道的),看看你是否認爲對於不瞭解你的問題的人有任何意義。 – Tanner

+0

其實他的問題很清楚 – NeedAnswers

+0

你到目前爲止試過的是什麼? – Nithesh

回答

2

這包括建立測試數據,但我認爲這是你想要的東西:

測試數據:

DECLARE @Table TABLE 
(
    From_ID int, 
    TO_ID int 
) 
INSERT INTO @Table VALUES(1,3) 
INSERT INTO @Table VALUES(3,4) 
INSERT INTO @Table VALUES(4,5) 
INSERT INTO @Table VALUES(2,6) 
INSERT INTO @Table VALUES(6,3) 
INSERT INTO @Table VALUES(10,50) 

查詢得到答案:

;WITH Hierarchy (Employee, Superior, QueryLevel) 
AS 
(
    --root is all employees that have no subordinates 
    SELECT E.From_ID, E.TO_ID, 1 
    FROM @Table E 
    LEFT 
    JOIN @Table S 
      ON S.TO_ID = E.From_ID 
    WHERE S.TO_ID IS NULL 
    --recurse up tree to final superior 
    UNION ALL 
    SELECT H.Employee, S.TO_ID, H.QueryLevel + 1 
    FROM Hierarchy H 
    JOIN @Table S 
      ON S.From_ID = H.Superior 
) 
SELECT Employee, Superior 
FROM 
(
    SELECT *, ROW_NUMBER() OVER(PARTITION BY Employee ORDER BY QueryLevel DESC) AS RowNumber 
    FROM Hierarchy 
) H 
WHERE RowNumber = 1 

本質,這作品通過:

1)得到的所有員工沒有reportees(根)

2)通過凸臺遞歸起來,記錄該「等級」

3)使用上/分區只選擇「最終」老闆

+0

所以這意味着我必須創建此表或者這裏只是爲了測試目的? – Andrey

+0

僅用於測試目的 - 用已有的表替換@Table :) –

+0

查詢的唯一問題是:)'語句已終止。在完成陳述之前,最大遞歸100已經耗盡。「# – Andrey

2
WITH q (employee, boss) AS 
     (
     SELECT fromId, toId 
     FROM mytable 
     WHERE fromId NOT IN 
       (
       SELECT toId 
       FROM mytable 
       ) 
     UNION ALL 
     SELECT employee, toId 
     FROM q 
     JOIN mytable t 
     ON  t.fromId = boss 
     ) 
SELECT * 
FROM q 
WHERE boss NOT IN 
     (
     SELECT fromId 
     FROM mytable 
     ) 
+0

正在準備與你發佈的類似的答案,所以你可以添加這個小提琴與你的代碼,如果你喜歡:http://sqlfiddle.com/#!3/98a38/1 – Tanner

2

你可以嘗試這樣的事情嗎?

DECLARE @Employees TABLE (
    EmployeeId INT, 
    PositionName VARCHAR(50), 
    ReportsToId INT); 
INSERT INTO @Employees VALUES (1, 'Driver', 3); 
INSERT INTO @Employees VALUES (3, 'Head of Driving Pool', 4); 
INSERT INTO @Employees VALUES (4, 'Corporate Flunky', 5); 
INSERT INTO @Employees VALUES (2, 'Window Cleaner', 6); 
INSERT INTO @Employees VALUES (6, 'Head of Office Services', 3); 
INSERT INTO @Employees VALUES (10, 'Minion', 50); 
INSERT INTO @Employees VALUES (5, 'BOSS', NULL); 
INSERT INTO @Employees VALUES (50, 'BOSS2', NULL); 
WITH Employees AS (
    SELECT 
     EmployeeId, 
     1 AS [Level], 
     EmployeeID AS [Path], 
     ISNULL(ReportsToId, EmployeeId) AS ReportsToId 
    FROM 
     @Employees 
    WHERE 
     ReportsToId IS NULL 
    UNION ALL 
    SELECT 
     e.EmployeeID, 
     x.[Level] + 1 AS [Level], 
     x.[Path] + e.EmployeeID AS [Path], 
     x.ReportsToId 
    FROM 
     @Employees e 
     INNER JOIN Employees x ON x.EmployeeID = e.ReportsToId) 
SELECT 
    ec.EmployeeId, 
    e.PositionName, 
    ec.[Level], 
    CASE WHEN ec.ReportsToId = ec.EmployeeId THEN NULL ELSE ec.ReportsToId END AS ReportsToId --Can't really report to yourself 
FROM 
    Employees ec 
    INNER JOIN @Employees e ON e.EmployeeId = ec.EmployeeId 
ORDER BY 
    ec.[Path];