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

@a_horse_with_no_name 논리적으로, "빌딩"레벨은 캠퍼스 이름 인 부모, 즉 "MAINCAMPUS"부모를 가진 것입니다. 모든 노드의 루트는 "MAINCAMPUS"의 부모 인 "COMPANYNAME"이며 모든 건물 ( "grounds"포함)은 MAINCAMPUS를 부모로 갖습니다.
SeanKilleen

와! 어떻게 만들었 어 !! 구글은 "SQL의 인접성 (adjacency) 모델"에 대한 모든 설정됩니다
srini.venigalla

추신 : 다이어그램을 만드는 방법에 관심이있는 사람들을 위해 asciiflow.com 이라는 멋진 웹 사이트를 사용했습니다. 저는 그런 상황에 큰 팬입니다.
SeanKilleen

답변:


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


답변 주셔서 감사합니다! 나는 내 질문을 잘 표현하지 못했다고 생각하기에 충분합니다. 내 테이블 구조에는 "location"과 "parent"라는 두 개의 열이 있습니다. 이 계층 구조는 내 ASCII 차트에 의해 정의됩니다. "건물"수준의 각 위치에 대해 지점 아래의 모든 위치를 보여주는 뷰를 구성하고 싶습니다. 저의 목표는 뷰를 통해 건물을 쿼리하고 모든 하위 위치를 가져 오거나 하위 위치를 쿼리하고 해당 건물이 속한 건물을 볼 수 있도록하는 것입니다. 어떤 도움이라도 대단히 감사하겠습니다!
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;

각 위치의 계층 구조가 표시됩니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.