2009-11-16 9 views
4

Oracle 10g 사용. 나는 두 개의 테이블을 가지고있다.오라클 계층 적 쿼리

User Parent 
------------- 
1  (null) 
2  1 
3  1 
4  3 

Permission User_ID 
------------------- 
A   1 
B   3 

권한 테이블의 값은 하위로 상속된다.

User Permission 
------------------ 
1  A 
2  A 
3  A 
3  A 
3  B 
4  A 
4  B 

은 이전 수준에서 행에 끌어 구문으로 10g이 .. 연결하여 이러한 쿼리를 공식화 할 수 있는가 : 나는 나에게 이런 일을 반환 할 수 단일 쿼리를 작성 하시겠습니까?

답변

3

당신은에 의해 연결 (루트 노드의 열 값을 반환하는 기능 CONNECT_BY_ROOT)으로 원하는 결과를 얻을 수 있습니다 :

SQL> WITH users AS (
    2  SELECT 1 user_id, (null) PARENT FROM dual 
    3  UNION ALL SELECT 2, 1 FROM dual 
    4  UNION ALL SELECT 3, 1 FROM dual 
    5  UNION ALL SELECT 4, 3 FROM dual 
    6 ), permissions AS (
    7  SELECT 'A' permission, 1 user_id FROM dual 
    8  UNION ALL SELECT 'B', 3 FROM dual 
    9 ) 
10 SELECT lpad('*', 2 * (LEVEL-1), '*')||u.user_id u, 
11   u.user_id, connect_by_root(permission) permission 
12 FROM users u 
13 LEFT JOIN permissions p ON u.user_id = p.user_id 
14 CONNECT BY u.PARENT = PRIOR u.user_id 
15 START WITH p.permission IS NOT NULL 
16 ORDER SIBLINGS BY user_id; 

U   USER_ID PERMISSION 
--------- ------- ---------- 
3    3 B 
**4    4 B 
1    1 A 
**2    2 A 
**3    3 A 
****4   4 A 
+0

일이 connect_by_root에 대해 알고하지 않았다. 제 버전은 9i에서 작동하지만, 당신의 방법이 더 좋습니다. –

0

한 번 봐 걸릴 수 있습니다. proc을 사용하여 모두 루프 할 수 있습니다.

CREATE TABLE a_lnk 
(user_id VARCHAR2(5), 
parent_id VARCHAR2(5)); 

CREATE TABLE b_perm 
(perm VARCHAR2(5), 
user_id VARCHAR2(5)); 


INSERT INTO a_lnk 
    SELECT 1, NULL 
    FROM DUAL; 

INSERT INTO a_lnk 
    SELECT 2, 1 
    FROM DUAL; 

INSERT INTO a_lnk 
    SELECT 3, 1 
    FROM DUAL; 


INSERT INTO a_lnk 
    SELECT 4, 3 
    FROM DUAL; 

INSERT INTO b_perm 
    SELECT 'A', 1 
    FROM DUAL; 

INSERT INTO b_perm 
    SELECT 'B', 3 
    FROM DUAL; 

-- example for just for user id = 1 
-- 
SELECT c.user_id, c.perm 
    FROM b_perm c, 
     (SELECT  parent_id, user_id 
       FROM a_lnk 
     START WITH parent_id = 1 
     CONNECT BY PRIOR user_id = parent_id 
     UNION 
     SELECT  parent_id, user_id 
       FROM a_lnk 
     START WITH parent_id IS NULL 
     CONNECT BY PRIOR user_id = parent_id) d 
WHERE c.user_id = d.user_id 
UNION 
SELECT d.user_id, c.perm 
    FROM b_perm c, 
     (SELECT  parent_id, user_id 
       FROM a_lnk 
     START WITH parent_id = 1 
     CONNECT BY PRIOR user_id = parent_id 
     UNION 
     SELECT  parent_id, user_id 
       FROM a_lnk 
     START WITH parent_id IS NULL 
     CONNECT BY PRIOR user_id = parent_id) d 
WHERE c.user_id = d.parent_id; 
1

마술의 종류,하지만 당신은 테이블 캐스트 MULTISET 절은 WHERE에 서로 하나 개의 테이블을 참조하는 데 사용할 수 있습니다

서브 쿼리 x에서
create table t1(
    usr number, 
    parent number 
); 

create table t2(
    usr number, 
    perm char(1) 
); 

insert into t1 values (1,null); 
insert into t1 values (2,1); 
insert into t1 values (3,1); 
insert into t1 values (4,3); 

insert into t2 values (1,'A'); 
insert into t2 values (3,'B'); 

select t1.usr 
    , t2.perm 
    from t1 
    , table(cast(multiset(
     select t.usr 
      from t1 t 
     connect by t.usr = prior t.parent 
      start with t.usr = t1.usr 
     ) as sys.odcinumberlist)) x 
    , t2 
where t2.usr = x.column_value 
; 

내가 모든 부모의 테이블을 구성을 해당 사용자를 t1 (그 자체 포함)에서 가져온 다음이 부모에 대한 사용 권한으로 가입하십시오.