Oracle 11g 使用 CONNECT BY 和多个表创建视图
Posted
技术标签:
【中文标题】Oracle 11g 使用 CONNECT BY 和多个表创建视图【英文标题】:Oracle 11g CREATE VIEW using CONNECT BY and multiple tables 【发布时间】:2012-04-11 01:45:51 【问题描述】:使用 Oracle 11G(不是 R2)数据库,我们需要创建报告,显示个人的报告结构属于哪个领导委员会。
在较高级别上,我们通过在 board_members 表中查找员工 ID 来确定个人在董事会中的存在。
board_members 表有一个职位 ID,可用于访问 board_positions,从那里我们可以确定该职位是否在领导委员会中。 (以下示例。)
对于领导委员会中的任何员工,他自己的 ID 将代表 BOARD_LEAD。
对于任何其他员工,report_to 值会递归,直到确定领导委员会成员,并且该人的 ID 将为 BOARD_LEAD。
我们的***员工有 report_to 等于他们自己的 empl_id,而不是更常见的 NULL。
为了展示这一点,我在下面设置了示例表、示例数据和示例所需的输出。
我正在尝试了解如何创建一个视图,该视图将为全职等效和其他报告需求提供此类信息。我确信 CONNECT BY 将参与其中,但我发现 Oracle 文档令人困惑,并且我没有发现包含多个表的示例。 (我担心缺乏例子是有充分理由的。)
是否甚至可以在 Oracle 11g(不是 R2)上编写这样的视图,而不是必须随每次位置变化而更新的中间表?
Create table board_positions /* If board_position = 'LDRSHPCOMM' this is a top position */
(member_id varchar(6),board_position varchar(18));
Create table board_members
(empl_id varchar(6), member_id varchar(6));
Create table emp
(empl_id varchar(6),ename varchar(32),report_to varchar(6));
Insert into board_positions values('CEO','LDRSHPCOMM');
Insert into board_positions Values('COO','LDRSHPCOMM');
Insert into board_positions Values('CFO','LDRSHPCOMM');
Insert into board_positions Values('CIO','LDRSHPCOMM');
Insert into board_positions values('WANABE','NEWBIE');
Insert into emp ('TOPDOG','Big Guy','TOPDOG');
Insert into emp ('WALLET','Money Bags','TOPDOG');
Insert into emp ('OPSGUY','Meikut Work','TOPDOG');
Insert into emp ('INFGUY','Comp U Turk','TOPDOG');
Insert into emp ('HITECH','Number 2','INFGUY');
Insert into emp ('LOTECH','Number 3','HITECH');
Insert into emp ('PROGMR','Nameless Blameless','LOTECH');
insert into emp ('FLUNKY','Ida Dunnit','PROGMR');
Insert into board_members ('TOPDOG','CEO');
Insert into board_members ('WALLET','CFO');
Insert into board_members ('OPSGUY','COO');
Insert into board_members ('INFGUY','CIO');
Insert into board_members ('HITECH','WANABE'); /* Board position not on the leadership committee */
使用类似的东西:
CREATE VIEW LEADER_VIEW AS
WITH T1 AS (SELECT e.empl_id, (something) as board_lead
, (something) as board_lead_pos
FROM emp e
LEFT OUTER JOIN board_members bm
ON bm.empl_id = e.empl_id
LEFT OUTER JOIN board_positions bp
on bp.member_id = bm.member_id
...
CONNECT BY PRIOR empl_id = report_to
START WITH empl_id = report_to
)
SELECT * FROM T1
(但我知道它的意义远不止于此!)
所需的输出示例。 . .
TOPDOG TOPDOG CEO (Because self is on LDRSHPCOMM)
WALLET WALLET CFO (Because self is on LDRSHPCOMM)
OPSGUY OPSGUY COO (Because self is on LDRSHPCOMM)
INFGUY INFGUY CIO (Because self is on LDRSHPCOMM)
HITECH INFGUY CIO (Because REPORTTO is on LDRSHPCOMM)
LOTECH INFGUY CIO (Because REPORTTO->REPORTTO is on LDRSHPCOMM)
PROGMR INFGUY CIO (REPORTTO->REPORTTO->REPORTTO is on LDRSHPCOMM)
FLUNKY INFGUY CIO (You know by now.)
【问题讨论】:
【参考方案1】:你可以这样做:
SQL> SELECT *
2 FROM (SELECT empl_id, ename, report_to,
3 member_id, board_position,
4 MAX(lvl) over(PARTITION BY empl_id) maxlvl, lvl
5 FROM (SELECT connect_by_root(e.empl_id) empl_id,
6 connect_by_root(e.ename) ename,
7 bm.empl_id report_to,
8 LEVEL lvl, bp.*
9 FROM emp e
10 LEFT JOIN board_members bm
11 ON e.empl_id = bm.empl_id
12 LEFT JOIN board_positions bp
13 ON bm.member_id = bp.member_id
14 CONNECT BY NOCYCLE e.empl_id = PRIOR e.report_to
15 AND (PRIOR bp.board_position IS NULL
16 OR PRIOR bp.board_position != 'LDRSHPCOMM')))
17 WHERE lvl = maxlvl;
EMPL_ID ENAME REPORT_TO MEMBER_ID BOARD_POSITION
------- -------------------------------- --------- --------- ------------------
FLUNKY Ida Dunnit INFGUY CIO LDRSHPCOMM
HITECH Number 2 INFGUY CIO LDRSHPCOMM
INFGUY Comp U Turk INFGUY CIO LDRSHPCOMM
LOTECH Number 3 INFGUY CIO LDRSHPCOMM
OPSGUY Meikut Work OPSGUY COO LDRSHPCOMM
PROGMR Nameless Blameless INFGUY CIO LDRSHPCOMM
TOPDOG Big Guy TOPDOG CEO LDRSHPCOMM
WALLET Money Bags WALLET CFO LDRSHPCOMM
我没有 START WITH 子句,因为我想为所有员工启动分层查询。对于每个员工,我都会遍历层级数据,直到找到一位担任领导委员会董事会成员的经理(CONNECT BY 子句)。
外部查询过滤相关行。
【讨论】:
以上是关于Oracle 11g 使用 CONNECT BY 和多个表创建视图的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Oracle 11g 中使用 group by 和 pivot
ORACLE 的CONNECT BYSTART WITH,CONNECT_BY_ROOTCONNECT_BY_ISLEAFSYS_CONNECT_BY_PATH,LEVEL的使用(Hierarc(代码