2014-06-23 48 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];