我需要所有员工的列表,遵循管理器的层次结构,使用下表中的MYSQL。在oracle或mssql中这很容易,但在MySQL中找不到任何解决方案。任何人都可以帮我解决问题。
id name manager
1 John 6
2 Gill 7
3 Ben 2
4 Roy 8
5 Lenin 6
6 Nancy 7
7 Sam 0
8 Dolly 3
答案 0 :(得分:3)
如果仍然可以限制最大级别数,这是一个带递归过程的解决方案。由于MySQL中不允许使用递归函数,因此我们在这里有一个函数(manager_count),它包装了递归过程的结果。递归深度由max_sp_recursion_depth变量控制,takes 255 as its maximum。使用方法如下:SELECT *,manager_count(id) FROM my_table
。它不是最佳解决方案,因为它没有考虑已经计算的层次结构的分支(临时表实际上可以用作缓存)。
DELIMITER //
DROP FUNCTION IF EXISTS manager_count//
CREATE FUNCTION manager_count(_manager INT) RETURNS INT
BEGIN
DECLARE _count INT DEFAULT 0;
SET max_sp_recursion_depth = 255;
# manager_count_helper does the job
CALL manager_count_helper(_manager, _count);
# subtract 1, because manager_count_helper will count this manager as well
RETURN _count - 1;
END//
DROP PROCEDURE IF EXISTS manager_count_helper//
CREATE PROCEDURE manager_count_helper(IN _manager INT, INOUT _count INT)
BEGIN
IF EXISTS (SELECT 1 FROM my_table WHERE id = _manager) THEN
BEGIN
DECLARE _next_manager INT DEFAULT 0;
DECLARE done BOOLEAN DEFAULT FALSE;
# cursor to loop through the employees
DECLARE _cursor CURSOR FOR SELECT id FROM my_table WHERE manager = _manager;
# if done, the done variable gets TRUE and it's time too leave
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
# count 1, because this guy should be counted as well
SET _count = _count + 1;
OPEN _cursor;
read_loop: LOOP
FETCH _cursor INTO _next_manager;
IF done THEN LEAVE read_loop;
END IF;
CALL manager_count_helper(_next_manager, _count);
END LOOP;
CLOSE _cursor;
END;
END IF;
END