2012-07-31 4 views
0

사용자 ID 값 테이블이 있습니다. A 열은 관리 사용자이고 B 열은 사용자를가집니다. 예를 들어 다른 사용자를 관리하는 사용자 목록을 표시 할 수 있기를 원합니다. 내가 계층 구조를 그들을 따라 관리 사용자의 목록을 반환하는 쿼리 또는 저장 프로 시저를하고 싶은MySQL에서 계층 적 데이터 집합 생성

 
-------------------------- 
| mgtuserId | userId | 
-------------------------- 
|  1  |  2 | 
|  1  |  3 | 
|  3  |  4 | 
|  5  |  6 | 
-------------------------- 

:

 
User 1 can manage user 2 
User 1 can manage user 3 
User 3 can manage user 4 
User 5 can manage user 6 

이 다음 표를 생성합니다. 따라서 사용자 1이면 다음 목록이 출력됩니다.

 1, 2, 3, 4

그러면 사용자 2 인 경우 2 개의 출력 만 표시됩니다.

 2

그런 다음 사용자 5이면 다음 목록이 출력됩니다.

 5, 6

나는 각 사용자 ID가 있기 때문에 이것을 달성하는 가장 좋은 방법은 무엇입니까?

미리 감사드립니다.

답변

1

CALL get_users(1); 
1 
2 
3 
4 

을 확인 테이블 이름

DELIMITER $$ 

CREATE PROCEDURE get_users(IN base INT UNSIGNED) 
BEGIN 
DECLARE ids TEXT DEFAULT ''; 

SET @parents = base; 
SET ids = base; 

loop1: LOOP 
    SET @stm = CONCAT(
     'SELECT GROUP_CONCAT(userId) INTO @parents FROM YOUR_TABLE', 
     ' WHERE mgtuserId IN (', @parents, ')' 
    ); 

    PREPARE fetch_childs FROM @stm; 
    EXECUTE fetch_childs; 
    DROP PREPARE fetch_childs; 

    IF @parents IS NULL THEN LEAVE loop1; END IF; 

    SET ids = CONCAT(ids, ',', @parents); 
END LOOP; 

SET @stm = CONCAT('(SELECT mgtuserId FROM YOUR_TABLE WHERE mgtuserId=',base,') UNION (SELECT userId FROM YOUR_TABLE WHERE userId IN (',ids, '))'); 

PREPARE fetch_childs FROM @stm; 
EXECUTE fetch_childs; 
DROP PREPARE fetch_childs; 
END; 

에 YOUR_TABLE를 교체하고있는 my.ini

설정
thread_stack = 256K 
0

검색어를 제공하려면 재귀 쿼리가 필요한 관계의 전이 폐쇄가 필요합니다. 필자가 아는 한, recusrive 쿼리는 스토어드 프로 시저 또는 함수의 도움을 제외하고는 MySQL에서 표현 될 수 없다.

위의 용어 중 일부를 a search에 사용하면 나와 관련이있는 많은 질문과 답변을 얻을 수 있습니다. how to work with recursive query in MySql?이 그 중 하나입니다. 거기에 대한 대답은 a document으로 연결되어 구현을위한 좋은 출발점이 될 수있는 PROCEDURE recursivesubtree을 설명합니다.

0

출력 사양에 따라 약간 다른 버전으로 연결됩니다.

"루프"가없고 mgtuserId = userId가있는 행이 없다고 가정하면

과 같이 여러 번 테이블에 조인하여 N 수준의 계층 적 쿼리를 에뮬레이트 할 수 있습니다
SELECT n0.userId AS n0_userId 
    , n1.userId AS n1_userId 
    , n2.userId AS n2_userId 
    , n3.userId AS n3_userId 
    , n4.userId AS n4_userId 
    , n5.userId AS n5_userId 
    , n6.userId AS n6_userId 
    FROM mytable n0 
    LEFT JOIN mytable n1 ON n1.mgtuserId = n0.userId 
    LEFT JOIN mytable n2 ON n2.mgtuserId = n1.userId 
    LEFT JOIN mytable n3 ON n3.mgtuserId = n2.userId 
    LEFT JOIN mytable n4 ON n4.mgtuserId = n3.userId 
    LEFT JOIN mytable n5 ON n5.mgtuserId = n4.userId 
    LEFT JOIN mytable n6 ON n6.mgtuserId = n5.userId 
WHERE n0.userId = 1 

그러나이 쿼리는 지정한 결과 집합 (쉼표로 구분 된 목록)을 반환하지 않습니다.

이 쿼리에서 반환하는 각 행은 지정한 시작 지점에서 각 리프 노드까지 트리 아래로 "경로"를 나타냅니다 (이 경우 깊이가 6 레벨 이하인 모든 노드 (지정된 시작 위치 아래 점).

아니, 그것은 꽤 아니에요.하지만 당신이 N 수준으로 확장 할 수있는 방법을 볼 수 있습니다.

을 지금, 나는 당신이 지정된 결과 집합이 변환 할 수있는 좋은 방법이 표시되지 않습니다

나는 같은 종류의 일을해야 할 수도 있지만 별도의 쿼리 (한 수준 깊은, 두 수준 깊이 등) 및 t 암탉은 그들을 결합하기 위해 UNION ALL을 사용합니다. 그러나 그것은 심지어 더 못 생길 것입니다.

불특정 다수의 레벨을 각 리프 노드로 가져 오려면 임시 테이블을 사용해야하며 동일한 유형의 쿼리를 반복적으로 수행해야합니다. 물론 그것은 단일 쿼리가 아닙니다.

(나는 당신의 지정된 결과 집합을 반환하는 솔루션을 작동합니다.)