使用mysql的经理下的员工的递归计数

时间:2013-12-12 11:31:14

标签: php mysql

我需要所有员工的列表,遵循管理器的层次结构,使用下表中的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

1 个答案:

答案 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