2

我在一次工作面试中得到了以下问题,它完全把我难住了,所以我想知道是否有人可以帮我解释一下。假设我有下表:

employees
--------------------------
id | name     | reportsTo
--------------------------
 1 | Alex     | 2
 2 | Bob      | NULL
 3 | Charlie  | 5
 4 | David    | 2
 5 | Edward   | 8
 6 | Frank    | 2
 7 | Gary     | 8
 8 | Harry    | 2
 9 | Ian      | 8

问题是编写一个 SQL 查询,该查询返回一个表,其中有一列代表每个员工的姓名,一列显示组织中该员工之上的人数:即,

hierarchy
--------------------------
name     | hierarchyLevel
--------------------------
Alex     | 1
Bob      | 0
Charlie  | 3
David    | 1
Edward   | 2
Frank    | 1
Gary     | 2
Harry    | 1
Ian      | 2

我什至不知道从哪里开始将其编写为 SQL 查询(也许是游标?)。如果我再次被问到类似的问题,谁能帮助我?谢谢。

4

1 回答 1

2

最简单的示例是使用(真实或临时)表,并一次添加一个级别(小提琴):

INSERT INTO hierarchy
SELECT id, name, 0
FROM employees
WHERE reportsTo IS NULL;

WHILE ((SELECT COUNT(1) FROM employees) <> (SELECT COUNT(1) FROM hierarchy))
BEGIN
    INSERT INTO hierarchy
    SELECT e.id, e.name, h.hierarchylevel + 1
    FROM employees e
    INNER JOIN hierarchy h ON e.reportsTo = h.id
    AND NOT EXISTS(SELECT 1 FROM hierarchy hh WHERE hh.id = e.id)
END

对于每个 RDBMS,其他解决方案将略有不同。例如,在 SQL Server 中,您可以使用递归 CTE 来扩展它(小提琴):

;WITH expanded AS
(
    SELECT id, name, 0 AS level
    FROM employees
    WHERE reportsTo IS NULL
    UNION ALL
    SELECT e.id, e.name, level + 1 AS level
    FROM expanded x
    INNER JOIN employees e ON e.reportsTo = x.id
)
SELECT * 
FROM expanded
ORDER BY id

其他解决方案包括递归存储过程,甚至使用动态 SQL 迭代地增加连接数,直到每个人都被考虑在内。

当然,所有这些示例都假设没有循环,并且每个人都可以沿着链条向上追踪到头部(reportsTo = NULL)。

于 2013-08-09T18:27:06.107 回答