Oracle Hierarchical Queries
我正在努力处理具有以下要求的查询:
表A
1 2 3 4 5 | ID Name Key 1 A1 Key1 2 A2 Key2 3 A3 Key3 |
表B
1 2 3 4 5 6 7 8 | ID A_ID NAME CONTAINER_A_ID 1 1 B1 NULL 2 1 B2 NULL 3 1 B3 2 4 2 B4 NULL 5 2 B5 NULL 6 3 B6 NULL 7 3 B7 NULL |
表 A 中的 Key 列是唯一的
表B中的A_ID列是表A的外键
表 B 中的 CONTAINER_A_ID 列表示表 B 中的行可以是
容器,它包含由 CONTAINER_A_ID 值指示的其他数据行。
下面是例子:
输入参数为表A键列值,假设A.Key = \\'key1\\',根据上述样本数据得出的结果为:
1 2 3 4 5 6 | A.ID A.NAME A.KEY B.ID B.A_ID B.NAME B.CONTAINER_A_ID 1 A1 KEY1 1 1 B1 NULL 1 A1 KEY1 2 1 B2 NULL 1 A1 KEY1 3 1 B3 2 2 A2 KEY2 4 2 B4 NULL 2 A2 KEY2 5 2 B5 NULL |
如果输入参数是A.Key = \\'key2\\',则结果为:
1 2 3 | A.ID A.NAME A.KEY B.ID B.A_ID B.NAME B.CONTAINER_A_ID 2 A2 KEY2 4 2 B4 NULL 2 A2 KEY2 5 2 B5 NULL |
谢谢
这是用于分层查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | with TableA as ( select 1 id, 'A1' Name, 'Key1' key from dual union all select 2, 'A2', 'Key2' from dual union all select 3, 'A3', 'Key3' from dual ) , tableb as ( select 1 id, 1 a_id, 'B1' name , null CONTAINER_A_ID from dual union all select 2 , 1 , 'B2' , null from dual union all select 3 , 1 , 'B3' , 2 from dual union all select 4 , 2 , 'B4' , null from dual union all select 5 , 2 , 'B5' , null from dual union all select 6 , 3 , 'B6' , null from dual union all select 7 , 3 , 'B7' , null from dual ) select a.id, a.name, a.key, b.id, b.a_id, b.name, b.container_a_id from tableb b left join tablea a on a.id = b.a_id start with A.Key = 'Key1' connect by prior b.container_a_id = b.a_id; |
如果您需要订购,请在末尾添加
这是在 Oracle 11g 上。
如果您专门寻找 CONNECT BY,我还不知道。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | drop table t1; drop table t2; create table t1 (id int primary key, name char(5), key char(5)); create table t2 (id int primary key, a_id int, name char(5) , container int); insert into t1 values (1, 'A1', 'K1'); insert into t1 values (2, 'A2', 'K2'); insert into t1 values (3, 'A3', 'K3'); insert into t2 values (1, 1, 'B1', null); insert into t2 values (2, 1, 'B2', null); insert into t2 values (3, 1, 'B3', 2); insert into t2 values (4, 2, 'B4', null); insert into t2 values (5, 2, 'B5', null); insert into t2 values (6, 3, 'B6', null); insert into t2 values (7, 3, 'B7', null); with t(id, name, key, bid, aid, bname, con) as ( select a.id, a.name, a.key, b.id, b.a_id, b.name, b.container from t1 a inner join t2 b on a.id = b.a_id where a.key = 'K1' union all select a.id, a.name, a.key, b.id, b.a_id, b.name, b.container from t t inner join t1 a on a.id = t.con inner join t2 b on a.id = b.a_id ) select * from t; |
编辑:回应豪尔赫的评论
1 | insert into t2 values (4, 2, 'B4', 3); |
CTE 可以在 11g Oracle 中使用。我刚刚看到豪尔赫在我面前。如果您只是在 CTE 中使用 tableB 然后加入 CTE 以获取所有字段,则更容易看到递归是如何工作的,像这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | with recurse (a_id, b_id, parent_id) as (select a_id, id, container_a_id as parent_id from tableB WHERE A_ID = 1 -- Put your parameter here union all select b.a_id, b.id, b.container_a_id from recurse r, tableB b where b.a_id = r.parent_id ) select r.a_id, a.name, a.key, b.id, b.a_id, b.name, b.container_a_id from recurse r, tableA a, tableB b where r.a_id = a.id and r.b_id = b.id ; |
这得到了相同的结果,但是虽然您必须使用 a_id 而不是 a_key 作为条件,但理解递归要容易一些。
所以,把这个留在这里,以防它帮助人们了解一些关于 CTE 的知识。