Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 生成层次结构_Sql - Fatal编程技术网

Sql 生成层次结构

Sql 生成层次结构,sql,Sql,我在一次求职面试中遇到了下面的问题,这让我很困惑,所以我想知道是否有人能帮我解释一下。假设我有下表: employees -------------------------- id | name | reportsTo -------------------------- 1 | Alex | 2 2 | Bob | NULL 3 | Charlie | 5 4 | David | 2 5 | Edward | 8 6 | Frank |

我在一次求职面试中遇到了下面的问题,这让我很困惑,所以我想知道是否有人能帮我解释一下。假设我有下表:

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查询(可能是游标?)来编写。如果我再次被问到类似的问题,有人能帮我吗?谢谢。

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

其他解决方案包括递归存储过程,甚至使用动态SQL迭代增加连接的数量,直到所有人都被计算在内


当然,所有这些例子都假设没有循环,每个人都可以在链上追踪到一个head honcho(
reportsTo=NULL
)。

如果你有n个级别,你需要在这里递归。如果它只有3个级别,一些连接加上case可以很容易地完成这项工作。这取决于数据库。有些具有内置解决方案,如Oracle的CONNECT BY。@Joe,Oracle 11g支持递归CTE语法,这是标准SQL。依我看,不鼓励使用非标准的语法连接。
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
;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