Oracle:如何查询层次表?


10

背景

这是为了构造一些我们将用于报告的视图。

我有一张位置表,关键字段是“ location”和“ parent”

这两个字段在层次上创建的结构与公司名称->校园名称->建筑物名称->楼层名称->房间名称相似。在这种情况下,公司名称保持不变,园区名称保持不变。

位置的结构通常如下所示:

                                 +-----------+
                                 | Org. Name |
                                 +-----+-----+
                                       |
                                 +-----v-----+
           +--------------------+|Campus Name|+---+--+-------------+
           |                     +--+--------+    |                |
           |                        |             |                |
           |                        |             |                |
        +--+-----+           +------+-+        +--+----+       +---+---+
    +--+| BLDG-01|+--+       | BLDG-02|        |BLDG-03|       |Grounds|
    |   +--------+   |       +--------+        +-------+       +-------+
  +-+------+   +-----+--+
  |Floor-01|   |Basement+-------+
  +-+------+   +--------+       |
    |                           |
    |                           |
    | +----------+      +-------+--+
    +-+Room 1-001|      |Room B-002|
      +----------+      +----------+

每个位置都链接回其父位置,该父位置最终是组织名称。当前,只有一个组织和一个校园。

目标

  • 我希望能够在“建筑物”级别查询任何给定位置下方的所有位置。这样一来,我可以返回给定建筑物内任何位置执行的工作单数量之类的信息。
  • 我希望能够确定哪个子位置属于哪个建筑物。本质上是相反的;我想从建筑物下面的任何一层去追溯到建筑物是什么。
  • 我希望这是一个观点。那就是说,我想有一个表格,该表格针对“建筑物”级别的每个项目,在左侧栏中列出该建筑物,并在右侧栏中列出该建筑物下的所有可能位置。这样,我将有一个列表,可以随时查询以查找哪些位置属于哪个建筑物。

尝试并做对

我试图通过可怕的构造视图,UNION查询等来做到这一点-所有这些似乎都不是一个好主意。我知道Oracle通过“ CONNECT BY”拥有一种机制。我只是不确定如何利用它。


如何识别“根”节点?是NULL他们的父母吗?您如何确定“建筑水平”?
a_horse_with_no_name 2012年

@a_horse_with_no_name从逻辑上讲,我认为“建筑物”级别将是任何以其校园名称为父代的东西,即任何以“ MAINCAMPUS”为父代的东西。所有节点的根都是“ COMPANYNAME”,它是“ MAINCAMPUS”的父级,所有建筑物(加上“地面”)都以MAINCAMPUS作为父级。
SeanKilleen

哇!您是如何创建的!Google将为“ SQL中的邻接模型”做好一切准备
-srini.venigalla,2012年

PS,对于那些对我如何制作图表感兴趣的人,我使用了一个漂亮的小网站asciiflow.com-我非常喜欢这种情况。
SeanKilleen

Answers:


4

FrusteratedWithFormsDesigner具有正确的方向(+1)。我认为这是您正在寻找的特定内容。

CREATE OR REPLACE VIEW BuildingSubs AS
   SELECT connect_by_root location "Building", location "SubLocation"
   FROM some_table l
   START WITH l.Location IN 
      (
         SELECT location FROM
         (
         SELECT level MyLevel, location FROM some_table 
         START WITH parent IS NULL 
         CONNECT BY PRIOR location=parent
         )
         WHERE MyLevel=3   
      )
   CONNECT BY PRIOR l.location = l.parent;

select * from BuildingSubs; 

Building             SubLocation        
-------------------- --------------------
BLDG-01              BLDG-01              
BLDG-01              Basement             
BLDG-01              Room B-002           
BLDG-01              Floor-01             
BLDG-01              Room 1-001           
BLDG-02              BLDG-02              
BLDG-03              BLDG-03              
Grounds              Grounds              

该视图完成了所有三个目标。您可以查询该建筑物以查找其包含的所有内容,也可以查询其子位置以查找其所在的建筑物。

drop table some_table;
create table some_table (Location Varchar2(20), Parent Varchar2(20));

insert into some_table values ('Org. Name',NULL);
insert into some_table values ('MAINCAMPUS','Org. Name');
insert into some_table values ('BLDG-01','MAINCAMPUS');
insert into some_table values ('BLDG-02','MAINCAMPUS');
insert into some_table values ('BLDG-03','MAINCAMPUS');
insert into some_table values ('Grounds','MAINCAMPUS');
insert into some_table values ('Floor-01','BLDG-01');
insert into some_table values ('Basement','BLDG-01');
insert into some_table values ('Room B-002','Basement');
insert into some_table values ('Room 1-001','Floor-01');

如果您不想将建筑物本身算作子位置之一,则可以将现有查询合并为一个子查询,从而消除建筑物和子位置相同的条目。


莱,就是这样。感谢您的帮助!
SeanKilleen

9

CONNECT BY 是处理自然递归数据的正确方法。

我不知道您的桌子是什么样子,但也许是这样的:

SELECT *
FROM some_table st
START WITH st.location = 'BLDG-01'
CONNECT BY PRIOR st.location = st.parent;

这将使节点位于“ BLDG-01”下。

START WITH子句是您的基本情况。

另一种解释(除了Oracle,我认为您已经阅读并遇到了麻烦,它可能非常简洁):

http://www.adp-gmbh.ch/ora/sql/connect_by.html

也:

http://psoug.org/reference/connectby.html

和:

http://www.oradev.com/connect_by.jsp


感谢您的回复!我已经意识到我认为我的问题措辞不好。我的表结构有两列-“位置”和“父”。这些创建的层次结构由我的ascii图表定义。我想构建一个视图,该视图针对“建筑物”级别的每个位置显示其分支下的所有位置。我的目标是能够通过视图查询建筑物并获取其所有子位置,或查询子位置并查看建筑物属于哪个建筑物(因此查询中没有硬性定义的“ building-x”)。任何帮助将不胜感激!
SeanKilleen

2

我不确定我是否完全理解您的问题,但也许是这样的:

select location, 
       parent,
       sys_connect_by_path(location, '/') as item_list,
       case level
         when 1 then 'building'
         when 2 then 'floor'
         when 3 then 'room'
       end as item_type
from some_table 
start with parent = 'MAINCAMPUS'
connect by prior location = parent;

这将显示每个位置的层次结构

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.