Oracle: ฉันจะค้นหาตารางลำดับชั้นได้อย่างไร


10

พื้นหลัง

นี่คือการสร้างมุมมองบางอย่างที่เราจะใช้สำหรับการรายงาน

ฉันมีตารางของสถานที่คีย์ฟิลด์เป็น "สถานที่" และ "ผู้ปกครอง"

โครงสร้างที่สองฟิลด์นี้สร้างระดับที่ชาญฉลาดจะอยู่ในแนวเดียวกันกับชื่อ บริษัท -> ชื่อวิทยาเขต -> ชื่ออาคาร -> ชื่อชั้น -> ชื่อห้อง ชื่อ บริษัท ยังคงเหมือนเดิมและชื่อวิทยาเขตจะยังคงเหมือนเดิมในกรณีนี้

โครงสร้างของสถานที่โดยทั่วไปมีลักษณะดังนี้:

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

ทุกสถานที่เชื่อมโยงกลับไปยังตำแหน่งหลักซึ่งเป็นชื่อองค์กรในที่สุด ปัจจุบันมีเพียงหนึ่งองค์กรและหนึ่งวิทยาเขต

เป้าหมาย

  • ฉันต้องการที่จะสามารถค้นหาสถานที่ทั้งหมดที่อยู่ภายใต้สถานที่ที่กำหนดในระดับ "อาคาร" นี่คือดังนั้นฉันสามารถคืนสิ่งต่าง ๆ เช่นจำนวน workorders ได้ดำเนินการสำหรับตำแหน่งใด ๆ ภายในอาคารที่กำหนด
  • ฉันต้องการที่จะระบุตำแหน่งย่อยที่เป็นของอาคารใด โดยพื้นฐานแล้วตรงกันข้าม ฉันอยากจะไปจากทุกระดับที่อยู่ใต้ระดับอาคารและติดตามกลับไปที่สิ่งที่เป็นอาคาร
  • ฉันต้องการนี้จะเป็นในมุมมอง ซึ่งหมายความว่าฉันต้องการให้มีตารางสำหรับทุกรายการในระดับ "อาคาร" แสดงรายการสิ่งปลูกสร้างในคอลัมน์ซ้ายมือและตำแหน่งที่เป็นไปได้ทั้งหมดภายใต้อาคารนั้นในคอลัมน์ทางขวา วิธีนี้ฉันจะมีรายการที่ฉันสามารถสอบถามได้ตลอดเวลาเพื่อค้นหาว่าสถานที่ใดเป็นส่วนหนึ่งของสิ่งปลูกสร้าง

พยายามและทำมันถูกต้อง

ฉันพยายามทำสิ่งนี้ผ่านมุมมองที่สร้างขึ้นอย่างน่ากลัวคำถามของ UNION ฯลฯ ซึ่งทั้งหมดดูเหมือนจะเป็นความคิดที่ไม่ดี ฉันรู้ว่า Oracle มีกลไกสำหรับสิ่งนี้ผ่านทาง "CONNECT BY"; ฉันไม่แน่ใจว่าจะใช้ประโยชน์จากมันอย่างไร


โหนด "รูท" ถูกระบุอย่างไร? เป็นผู้ปกครองNULLสำหรับพวกเขา? คุณจะระบุ "ระดับอาคาร" ได้อย่างไร
a_horse_with_no_name

@a_horse_with_no_name อย่างมีเหตุผลฉันคิดว่าระดับ "สิ่งปลูกสร้าง" จะเป็นอะไรก็ได้กับผู้ปกครองที่ชื่อมหาวิทยาลัยคืออะไรก็ตามที่มีผู้ปกครองของ "MAINCAMPUS" รูทของโหนดทั้งหมดคือ "COMPANYNAME" ซึ่งเป็นพาเรนต์ของ "MAINCAMPUS" และสิ่งปลูกสร้างทั้งหมด (รวมถึง "บริเวณ") มี MAINCAMPUS เป็นพาเรนต์
SeanKilleen

ว้าว! คุณสร้างมันขึ้นมาได้อย่างไร !! Google สำหรับ "Adjacency Model in SQL" คุณจะพร้อมทุกอย่าง
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


ขอบคุณสำหรับคำตอบ! ฉันได้รับเพียงพอที่จะรู้ว่าฉันไม่คิดว่าฉันใช้ถ้อยคำของคำถามได้ดี โครงสร้างตารางของฉันมีสองคอลัมน์ - "สถานที่ตั้ง" และ "ผู้ปกครอง" ลำดับชั้นที่สร้างเหล่านี้ถูกกำหนดโดยแผนภูมิ 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;

นี่จะแสดงลำดับชั้นสำหรับแต่ละสถานที่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.