Oracle: Як я запитую ієрархічну таблицю?


10

Фон

Це для побудови деяких поглядів, які ми будемо використовувати для звітності.

У мене є таблиця місць розташування, ключові поля - "місцезнаходження" та "батьків" .

Структура, яку ці два поля створюють, рівняється, узгоджується з назвою компанії -> Назва кампусу -> Назва будівлі -> Назва поверху -> Назва кімнати. Назва компанії залишається такою ж, а назва кампусу залишається такою ж.

Структура локацій зазвичай виглядає так:

                                 +-----------+
                                 | 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". Корінь усіх вузлів - "COMPANYNAME", який є батьківським "MAINCAMPUS", і всі будівлі (плюс "підстави") мають MAINCAMPUS як батьків.
SeanKilleen

Оце Так! як ти це створив !! Google для "Модель суміжності в SQL" вам все буде налаштовано
srini.venigalla

PS, для тих, хто цікавився тим, як я склав схему, я використав чудовий маленький веб-сайт під назвою 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;

Це покаже вам ієрархію для кожного місця

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.