Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Oracle分层查询_Sql_Oracle_Oracle10g_Hierarchy - Fatal编程技术网

Sql Oracle分层查询

Sql Oracle分层查询,sql,oracle,oracle10g,hierarchy,Sql,Oracle,Oracle10g,Hierarchy,使用oracle10g。我有两张桌子: User Parent ------------- 1 (null) 2 1 3 1 4 3 Permission User_ID ------------------- A 1 B 3 权限表中的值将继承到子级。我想写一个查询,可以返回如下内容: User Permission ------------------ 1 A 2 A

使用oracle10g。我有两张桌子:

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 connect.来制定这样的查询。。按语法从以前的级别拉入行?

您可以查看一个用户id示例。您可以使用proc循环所有用户id

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;

有点像黑魔法,但您可以在WHERE子句中使用table cast multiset从一个表引用另一个表:

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
;

在子查询
x
中,我从
t1
为给定用户构造了一个包含所有父级的表(包括其本身),然后使用这些父级的权限将其连接起来。

您可以通过连接方式(以及返回根节点的列值的函数
connect\u by\u ROOT
)获得所需的结果:


+我不知道如何通过根连接。我的版本适用于9i,但你的版本更好。
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