Oracle: Bagaimana cara saya meminta tabel Hierarchical?

10

Latar Belakang

Ini untuk pembuatan beberapa tampilan yang akan kami gunakan untuk pelaporan.

Saya memiliki tabel lokasi, bidang kunci adalah "lokasi" dan "induk" .

Struktur yang dibuat oleh kedua bidang ini, berdasarkan level, ada di sepanjang baris Nama Perusahaan -> Nama Kampus -> Nama Bangunan -> Nama Lantai -> Nama Kamar. Nama perusahaan tetap sama dan nama Kampus tetap sama dalam hal ini.

Struktur lokasi umumnya terlihat seperti ini:

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

Setiap lokasi terhubung kembali ke lokasi induknya, yang pada akhirnya adalah nama organisasi. Saat ini, hanya ada satu organisasi dan satu kampus.

Tujuan

  • Saya ingin dapat menanyakan semua lokasi di bawah lokasi tertentu di tingkat "Bangunan". Ini agar saya dapat mengembalikan hal-hal seperti berapa banyak pekerjaan yang telah dilakukan untuk setiap lokasi dalam suatu bangunan.
  • Saya ingin dapat menentukan sub-lokasi mana yang termasuk dalam bangunan mana . Pada dasarnya kebalikannya; Saya ingin pergi dari level mana saja di bawah level gedung dan menelusuri kembali ke apa bangunan itu.
  • Saya ingin ini dilihat . Itu berarti, saya ingin memiliki tabel yang untuk setiap item di tingkat "bangunan", daftar bangunan di kolom sebelah kiri dan semua lokasi yang mungkin di bawah bangunan di kolom sebelah kanan. Dengan cara ini saya memiliki daftar yang dapat saya tanyakan kapan saja untuk menemukan lokasi mana yang merupakan bagian dari bangunan mana.

Mencoba dan Melakukannya dengan Benar

Saya telah berusaha melakukan ini melalui pandangan yang dibangun dengan mengerikan, pertanyaan UNION, dll - yang semuanya tampak seperti ide yang buruk. Saya tahu Oracle memiliki mekanisme untuk ini melalui "CONNECT BY"; Aku hanya tidak yakin bagaimana memanfaatkannya.

SeanKilleen
sumber
Bagaimana cara mengidentifikasi "root"? Apakah orang tua NULLuntuk mereka? Bagaimana Anda mengidentifikasi "tingkat bangunan"?
a_horse_with_no_name
@a_horse_with_no_name secara logis, saya kira level "bangunan" adalah apa saja dengan induk yang merupakan nama kampus, yaitu apa pun dengan induk "MAINCAMPUS". Akar semua node adalah "COMPANYNAME", yang merupakan induk dari "MAINCAMPUS", dan semua bangunan (ditambah "alasan") memiliki MAINCAMPUS sebagai induk.
SeanKilleen
Wow! bagaimana Anda membuat itu !! Google untuk "Adjacency Model in SQL" Anda akan siap
srini.venigalla
PS, bagi mereka yang tertarik pada bagaimana saya membuat diagram, saya menggunakan situs web kecil yang bagus bernama asciiflow.com - Saya penggemar berat untuk situasi seperti itu.
SeanKilleen

Jawaban:

4

FrusteratedWithFormsDesigner memiliki arah yang benar (+1). Inilah yang saya pikir Anda cari secara spesifik.

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              

Pandangan ini mencapai ketiga tujuan. Anda dapat meminta itu untuk bangunan untuk menemukan semua yang ada di dalamnya dan Anda dapat meminta itu untuk sub-lokasi untuk menemukan di mana bangunan itu berada.

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');

Jika Anda tidak ingin menghitung bangunan itu sendiri sebagai salah satu sub-lokasi, Anda dapat membungkus kueri yang ada di salah satu entri menghilangkan di mana bangunan dan sublokasi adalah sama.

Leigh Riffel
sumber
Leigh, ini persisnya. Terima kasih atas bantuannya!
SeanKilleen
9

CONNECT BY adalah cara yang benar untuk menangani data yang rekursif secara alami.

Saya tidak tahu seperti apa meja Anda tetapi mungkin seperti:

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

Ini harus mendapatkan node di bawah "BLDG-01".

The START WITHklausul adalah kasus dasar Anda.

Penjelasan lain (selain dari Oracle yang saya anggap sudah Anda baca dan bermasalah, mungkin sangat singkat):

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

Juga:

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

Dan:

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

FrustratedWithFormsDesigner
sumber
Terima kasih atas tanggapannya! Saya mendapatkan cukup untuk menyadari bahwa saya tidak berpikir saya mengucapkan pertanyaan saya dengan baik. Struktur tabel saya memiliki dua kolom - "lokasi" dan "induk". Hirarki yang dibuat ini ditentukan oleh bagan ascii saya. Saya ingin membuat tampilan yang menunjukkan, untuk setiap lokasi di tingkat "gedung", semua lokasi di bawah cabangnya. Tujuan saya adalah untuk dapat melakukan kueri bangunan dan mendapatkan semua sub-lokasi, atau permintaan sublokasi dan melihat di mana bangunan itu miliknya, melalui tampilan (jadi tidak ada "building-x" yang didefinisikan dengan jelas di kueri). Bantuan apa pun akan sangat dihargai!
SeanKilleen
2

Saya tidak yakin saya mengerti pertanyaan Anda sepenuhnya, tetapi mungkin sesuatu seperti ini:

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;

Ini akan menunjukkan kepada Anda hierarki untuk setiap lokasi

seekor kuda tanpa nama
sumber