Oracle:如何查询分层表?

Sea*_*een 10 oracle query hierarchy view

背景

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

我有一个位置表,关键字段是 "location" 和 "parent"

这两个字段创建的结构在级别上是沿着公司名称 --> 校园名称 --> 建筑物名称 --> 楼层名称 --> 房间名称。在这种情况下,公司名称保持不变,校园名称保持不变。

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

                                 +-----------+
                                 | Org. Name |
                                 +-----+-----+
                                       |
                                 +-----v-----+
           +--------------------+|Campus Name|+---+--+-------------+
           |                     +--+--------+    |                |
           |                        |             |                |
           |                        |             |                |
        +--+-----+           +------+-+        +--+----+       +---+---+
    +--+| BLDG-01|+--+       | BLDG-02|        |BLDG-03|       |Grounds|
    |   +--------+   |       +--------+        +-------+       +-------+
  +-+------+   +-----+--+
  |Floor-01|   |Basement+-------+
  +-+------+   +--------+       |
    |                           |
    |                           |
    | +----------+      +-------+--+
    +-+Room 1-001|      |Room B-002|
      +----------+      +----------+
Run Code Online (Sandbox Code Playgroud)

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

目标

  • 我希望能够在“建筑物”级别查询任何给定位置下的所有位置。这样我就可以返回诸如在给定建筑物内的任何位置执行了多少工单之类的信息。
  • 我希望能够确定哪个子位置属于哪个建筑物。本质上是相反的;我想从建筑物层下的任何层开​​始,追溯到建筑物是什么。
  • 我希望这是在视图中。这意味着,我想要一个表格,对于“建筑物”级别的每个项目,在左侧栏中列出建筑物,并在右侧栏中列出该建筑物下的所有可能位置。这样我就有了一个列表,我可以随时查询该列表以查找哪些位置是哪个建筑物的一部分。

尝试并正确行事

我曾试图通过构建可怕的视图、UNION 查询等来做到这一点——这似乎都是一个坏主意。我知道 Oracle 通过“CONNECT BY”拥有一种机制;我只是不确定如何使用它。

Fru*_*ner 9

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

我不知道你的桌子是什么样子,但可能是这样的:

SELECT *
FROM some_table st
START WITH st.location = 'BLDG-01'
CONNECT BY PRIOR st.location = st.parent;
Run Code Online (Sandbox Code Playgroud)

这应该在“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


Lei*_*fel 4

FusteratedWithFormsDesigner 有正确的方向(+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              
Run Code Online (Sandbox Code Playgroud)

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

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');
Run Code Online (Sandbox Code Playgroud)

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