これは、レポートに使用するいくつかのビューを作成するためのものです。
場所のテーブルがありますキーフィールドは "場所"と "親"です。
これら2つのフィールドが作成する構造は、レベルごとに、会社名->キャンパス名->建物名->フロア名->部屋名のラインに沿っています。この場合、会社名は変わりませんが、キャンパス名は変わりません。
ロケーションの構造は通常、次のようになります。
+-----------+
| Org. Name |
+-----+-----+
|
+-----v-----+
+--------------------+|Campus Name|+---+--+-------------+
| +--+--------+ | |
| | | |
| | | |
+--+-----+ +------+-+ +--+----+ +---+---+
+--+| BLDG-01|+--+ | BLDG-02| |BLDG-03| |Grounds|
| +--------+ | +--------+ +-------+ +-------+
+-+------+ +-----+--+
|Floor-01| |Basement+-------+
+-+------+ +--------+ |
| |
| |
| +----------+ +-------+--+
+-+Room 1-001| |Room B-002|
+----------+ +----------+
すべての場所は、親の場所(最終的には組織名)にリンクします。現在、組織とキャンパスは1つだけです。
私はひどく構築されたビュー、UNIONクエリなどを使用してこれを試みました-これらはすべて悪い考えのように思えました。 Oracleが「CONNECT BY」を介してこのためのメカニズムを持っていることを知っています。どうやって使うのかよくわからない。
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
ビューは3つすべての目標を達成します。建物を照会して、そこに含まれるすべてのものを見つけることができます。また、サブロケーションを照会して、それがどの建物にあるかを見つけることができます。
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');
建物自体をサブロケーションの1つとして数えたくない場合は、既存のクエリを1つにラップして、建物とサブロケーションが同じエントリを除外できます。
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
そして:
私はあなたの質問を完全に理解しているとは思いませんが、おそらく次のようなものです:
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;
これにより、各場所の階層が表示されます