Oracle - 具有复杂用户结构的递归SQL

时间:2014-02-15 16:34:58

标签: sql oracle recursion

我有一个复杂的层次结构,一个人可以成为团队的团队领导或其他团队的团队成员。下面我在sql中创建了简单的结构:

CREATE TABLE USERR (
  ID INTEGER NOT NULL,
  NAME VARCHAR(100)  
);

Create TABLE TEAM(
  ID INTEGER NOT NULL,
  NAME VARCHAR(100)  
);

CREATE TABLE ROLE_TYPE(
  ID INTEGER NOT NULL,
  NAME VARCHAR(100)
);

CREATE TABLE ROLEE(
  ID INTEGER NOT NULL,
  NAME VARCHAR(100),
  ROLE_TYPE_ID INTEGER
);

CREATE TABLE POSITIONN(
  ID INTEGER NOT NULL,
  TEAM_ID INTEGER,
  USER_ID INTEGER,
  ROLE_ID INTEGER
);

INSERT INTO USERR (ID,NAME) VALUES (1,'User 1');
INSERT INTO USERR (ID,NAME) VALUES (2,'User 2');
INSERT INTO USERR (ID,NAME) VALUES (3,'User 3');
INSERT INTO USERR (ID,NAME) VALUES (4,'User 4');
INSERT INTO USERR (ID,NAME) VALUES (5,'User 5');
INSERT INTO USERR (ID,NAME) VALUES (6,'User 6');
INSERT INTO USERR (ID,NAME) VALUES (7,'User 7');
INSERT INTO USERR (ID,NAME) VALUES (8,'User 8');

INSERT INTO ROLE_TYPE (ID,NAME) VALUES (1,'Leader');
INSERT INTO ROLE_TYPE (ID,NAME) VALUES (2,'Member');

INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (1,'Role 1',1);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (2,'Role 1',2);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (3,'Role 2',1);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (4,'Role 2',2);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (5,'Role 3',1);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (6,'Role 3',2);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (7,'Role 4',1);
INSERT INTO ROLEE (ID,NAME, ROLE_TYPE_ID) VALUES (8,'Role 4',2);


INSERT INTO TEAM (ID,NAME) VALUES (1,'Team 1');
INSERT INTO TEAM (ID,NAME) VALUES (2,'Team 2');
INSERT INTO TEAM (ID,NAME) VALUES (3,'Team 3');
INSERT INTO TEAM (ID,NAME) VALUES (4,'Team 4');
INSERT INTO TEAM (ID,NAME) VALUES (5,'Team 5');

-- user 1 is leader of team 1 - role 1
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (1,1,1,1);

-- user 2 is member of team 1  - role 1 
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (2,1,2,2);

-- user 2 is leader of team 2  - role 2 
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (3,2,2,3); 

-- user 3 is member of team 2  - role 2  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (4,2,3,4); 

-- user 3 is leader of team 3  - role 3  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (5,3,3,5);

-- user 4 is member of team 2  - role 2  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (6,2,4,4); 

-- user 5 is member of team 3  - role 3  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (7,3,5,6); 

-- user 5 is leader of team 4  - role 4  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (8,4,5,7); 

-- user 6 is member of team 4  - role 4  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (9,4,6,8); 

-- user 7 is member of team 4  - role 4  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (10,4,7,8); 

-- user 4 is leader of team 5  - role 3
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (11,5,4,5);

-- user 8 is member of team 5  - role 4  
INSERT INTO POSITIONN (ID,TEAM_ID,USER_ID,ROLE_ID) VALUES (12,5,8,6); 

问题是,是否有可能使用connect by或with structure从中获取层次结构?

我尝试了类似的东西,但显然它不起作用,因为我找不到创建层次结构的逻辑条件:

with q(name, id, parent_id, parent_name) as (
    select 
      USERr.name, USERR.id, 
      null as parent_id, null as parent_name 
    from USERR, TEAM, ROLE_TYPE, ROLEE, POSITIONN
    where USERR.ID = POSITIONN.USER_ID 
          AND POSITIONN.TEAM_ID = TEAM.ID 
          AND ROLE_TYPE.ID = ROLEE.ROLE_TYPE_ID 
          AND POSITIONN.ROLE_ID = ROLEE.ID
          AND ROLE_TYPE.NAME = 'Leader'
          AND USERR.id = 1
  union all
    select 
      USERR.name, USERR.id, 
      q.id as parent_id, q.name as parent_name 
    from USERR, TEAM, ROLE_TYPE, ROLEE, POSITIONN, q
    where USERR.ID = POSITIONN.USER_ID 
          AND POSITIONN.TEAM_ID = TEAM.ID 
          AND ROLE_TYPE.ID = ROLEE.ROLE_TYPE_ID 
          AND POSITIONN.ROLE_ID = ROLEE.ID
          AND ROLE_TYPE.NAME = 'Member'
          AND USERR.ID = q.id
)
select * from q

是否有可能接收到user3下的所有用户的结果?所以它应该返回:用户5,用户6和用户7,但不会返回用户8,因为它不在用户4下?

我想,如果我想拿这种数据我需要写一个函数来做,我是对的吗?

1 个答案:

答案 0 :(得分:1)

最好在位置表(如manager_id列)中获得领导者和下属之间的经典父子关系。我尝试制作一些东西,但因为这种关系是隐含的,我可能会错过一些东西 - 所以下面的代码只是一个想法:

SQL> SELECT u.name, PRIOR u.name manager  FROM
  2  POSITIONN p
  3  , USERR u
  4  , TEAM t
  5  , ROLEE r
  6  , ROLE_TYPE rt
  7  WHERE p.user_id = u.id
  8  AND p.team_id = t.id
  9  AND p.role_id = r.id
 10  AND r.role_type_id = rt.id
 11  AND (u.name != PRIOR u.name)
 12  START WITH u.name = 'User 3' AND rt.name = 'Leader'
 13  CONNECT BY (PRIOR t.id = t.id AND rt.name = 'Member'
 14  AND PRIOR rt.name = 'Leader') OR
 15  (PRIOR u.id = u.id AND rt.name = 'Leader'
 16   AND PRIOR rt.name = 'Member')
 17  /

NAME                 MANAGER                                                    
-------------------- --------------------                                       
User 5               User 3                                                     
User 6               User 5                                                     
User 7               User 5